How to Plugin Web Pages dynamically in ASP .NET (and update the plugin)? - asp.net

For regular assemblies one can use MEF to load assemblies dynamically. If a live update is required of those assemblies, the recommendation is to use AppDomains to host the dynamic assemblies (potentially one can use Managed Add-in Framework (MAF)). When requiring an update, the appdomain is stopped, the assemblies are updated and the appdomain is reloaded.
What about assemblies that are loaded by ASP .NET that contain that code behind classes? How can I update them without forcing a restart of the main appdomain. Is it possible to host some of my pages in a dynamic appdomain? How would you do that? Can this appdomain share login token and authentication stuff so the user doesn't have to re-login?
Thanks

MEF doesn't support AppDomain isolation, so unfortunately, even during recomposition, those assemblies that had previously been loaded are still loaded in the main web application AppDomain. There are two things you'd need to battle in ASP.NET:
Any changes to physical files (e.g. .aspx, .cshtml, etc), or any changes to configuration files (.config), or any changes to the \bin directory will cause the application to be recycled. This is due to two things, file monitoring of pages/configs, and file monitoring of the \bin directory (which is because by default ASP.NET uses shadow copying of files - this is recommended).
To use MEF in another AppDomain would require a hideous amount of cross-domain communication, either through serialisation or MarshalByRef, which I just don't think would ever be a clean implementation. Not sure how you would trigger BuildProvider instances used to dynamically compile your pages in another AppDomain either.
I'm wondering if you're thinking about this too much. Since IIS6, HTTP.SYS has managed the routing of incoming requests to the appropriate website, this is handled at the kernel level. Even if the main application did restart (which there are a variety of reasons why it could), no requests will be dropped, it would simply queue waiting for a new worker process before passing the request on. Sure, from the user's point of view, they may notice some idle time waiting for the new application to restart, but realistically, how often are you going to be making these changes?
A lot of application design suffers from over-engineering. You may want to design for every scenario, but realistically it is easier to maintain a system which is simple but extensible. In my opinion, wanting to do what you have specified would be classed as over-engineering. Keep it simple.

Using the session "StateServer" will preserve your authentication between app pool recycles (caused by file updates).
For your actual question:
Create a folder outside of your website that your app pool has access to.
Put your new assemblies in there
Have a Task/Thread/Web Service that reads the folder and loads the assemblies into the current App Domain
Assembly.LoadFrom(string) http://msdn.microsoft.com/en-us/library/1009fa28.aspx
The newer version of the assembly should take precedence when an instance is created
I guess your question is saying this method doesn't work? What error are you getting...

Related

Prevent sharing DLL in IIS/ASP.net

lets say I have two ASP MVC applications.
ProjectXXX
ProjectYYY - this is fork of ProjectXXX.
Both projects have same structure (project/assembly name), but it differs on some functionality (it will be deployed for other countries).
For testing purposes we deploy both applications on one server.
ProjectXXX - has own IIS pool
ProjectYYY - has own IIS pool
Problem
When I removed some functionality from assembly of ProjectXXX and run ProjectYYY it throws TypeLoadException : Could not load type 'Project.Namespace.IMyInterface' from assembly 'Project.Namespace'
It looks like ProjectYYY uses DLL from ProjectXXX (IIS (asp.net?) loads dll once, because it "thinks" assemblies are the same?)
How to force IIS not to cache those assemblies and load the proper one for both apps?
EDIT / SOLUTION:
I have found, that my application uses MEF composition. As for now I have changed how it searches for assemblies and problem looks like gone :)
if you create separate IIS Site for each, it should do the trick, as for each site a separate w3wp process is run. Having said that, you can't share same ip and port for 2 sites so if you need that, you'll have to play around with redirecting, url rewriting on IIS.

Can you publish asp.net webforms project keeping it online?

We've quite a big project at work which sometimes needs to be published during the day. However, the application will (of course) crash during publish and show errors. (because the /bin is being overwritten)
Is there a way to avoid this? Sometimes a publish takes up to 3-4 minutes.
I know I can use the app_offline.htm file to display a message instead of them seeing the actual errors.
There isn't a way to have 0 downtime on a deployment. But you have some options
Deploy a pre-compiled site
To speed up the time taken for a site to be active after deployment, you can use ASP.NET Web Site Pre-compilation. This process will package the site so that it will not need to be compiled on-the-fly after deployment.
Benefits
Faster site startup
Less assets to deploy
Can be packaged via the Web Deployment Tool
Drawbacks
Debugging can be harder as the names are scrambled; Debug mode can be turned on for it though
You cannot edit a pre-compiled site; you must do a full re-deployment
You should still use the app_offline.htm so avoid yellow-screen-of-death errors
Add another web server
The best option for these scenarios is to have 2 servers with a load balancer in front of them. Then this way you use the load balancer to redirect active traffic to one node while the new application is being deployed.
Benefits
Parallel deployments do not affect the existing site
Have double the capacity for future expansion
Load balancing allows the load to be spread evenly across servers.
Drawbacks
Session now needs to be stored out-of-process. Therefore, you must check you can switch to an out-of-process session storage to confirm you do not have any serialization problems. StateServer is a quick one to get started with locally.
More maintenance overhead for a deployment, as you need to include load balancing configuration as part of your deployment processes. Network Admins are normally familiar with this.

Setting up DLLs so we can update production ASP.NET app w/o full publish or app restart

We have DLLs that contain hundreds of custom client processes that are kicked off from an ASP.NET application. Our clients run these processes while performing data entry, and typically there's only 1 process per client. On any given day, we might update 2 or 3 of these processes.
Currently these are all housed in a series of DLLs, which means that we are publishing our application a couple times per day. As a result, any logged-in clients get booted out of the system since the publish causes an app restart.
Is there a way that we can update these DLLs without requiring a full publish each time?
If your client processes have a common API then you could host, the DLLs separately in a WCF (or similar) service, and call the client processes remotely. So basically, consider moving to a service oriented architecture.
Check out the Managed Extensibility Framework (MEF) from Microsoft. It provides not only dependency management but also plug-in like library loading. Most likely it's exactly what you're looking for.
You can switch to SQL server or state server sessions in order to perserve session and logged users after app restart. Or store these dlls in APP_DATA and load it dinamically. Then of course you have to think of some refreshing system and refresh loaded dlls with newly uploaded ones.
There is no sensible way to avoid an application restart. Please note the emphasis on the word sensible.

ASP.Net JIT Compiler

I am experiencing slow response times on a web server hosting several asp.net applications. I do not precompile my apps so I understand that the first request to an application will take some time to load (5 to 10 secs). However, if an application has been idle for some time (20-30 minutes) the response is still slow even though I have set the "Idle Timeout" to 0 for the app pool in IIS 7.5. Therefore, I am considering writing a Windows service that will send requests to the individual apps every 10 minutes to keep them alive. My question is how does the JIT compiler handle subdirectories in an app. Does the JIT compiler compile all code for an app when you request a single page or does it do just enough to process the current request?
So when I write the Windows service can I just send a request to a single page in the app or do I need to send a request to a page in each subdirectory as well?
Thanks.
The model ASP.NET generally uses creates separate assemblies for the contents of the App_Code directory as well as the global.asax file, and then compiles all of the .aspx pages in each directory into a separate assembly (upon request).
User controls and Master Pages are also typically compiled independently from .aspx pages. I'm assuming you're using the "Updateable" option when you deploy. In that case
the app_code folder gets compiled at
deployment time
Code behind files for .aspx and master pages are compiled at deployment time
For each directory - all code behind files are complied into separate assemblies at deployment time
If you have a global.asax, then that gets compiled at the first request
All ascx and .master files are compiled at the time of a request (by folder) into separate assemblies.
So given the above, you'd have to make requests to at least one page in each folder, to keep the site "hot".
If you've used the "Fixed Names" option then you'll have many more assemblies but this option is also the best for when you want to be able to update the .aspx files. But be sure to test your site and compile performance on the production server.
Take a look at this:
The new "auto start" feature of
ASP.NET 4 and IIS 7.5 provides a
well-defined approach that allows you
to perform expensive application
startup and pre-cache logic that can
run before any end-users hit your
application. This enables you to have
your application "warmed up" and ready
from the very beginning, and deliver a
consistent high performance
experience.
Auto-Start ASP.NET Applications (VS 2010 and .NET 4.0 Series)

What exactly is Appdomain recycling

I am trying to figure out what exactly is Appdomain recycling?
When a aspx page is requested for the first time from a DotNet application, i understand that an appdomain for that app is created, and required assemblies are loaded into that appdomain, and the request will be served.
Now, if the web.config file or the contents of the bin folder, etc are modified, the appdomain will be "recycled".
My question is, at the end of the recycling process, will the appdomain be loaded with assemblies and ready to serve the next request? or a page has to be requested to trigger the assemblies to load?.
Well, I think the thread was getting smoothly to a final conclusion, but in the end, it was otherwise.
I'll try to answer the question based on my understanding and leveraging what i've just read about in other web sites.
First of all, I myself try to avoid the term recycle other than for Application Pools since this may render someone confused. Now, getting to process, pools and AppDomain, I see the picture as follows:
An Application Pool is, in short, a region of memory that is maintained up and running by a process called W3WP.exe, aka Worker Process. Recycling an Application Pool means bringing that process down, eliminating it from memory and then originating a brand new Worker Process, with a newly assigned process ID.
Regarding Application Domains, I see it as subsets of memory regions, within the aforementioned region that plays the role of a container. In other words, the process in memory, W3WP.exe in this case, is a macro memory region for applications that stores subset regions, called Application Domains. Having said that, one process in memory may store different Application Domains, one for each application that is assigned to run within a given Application Pool.
When it comes to recycling, as I initially told, it's something that I myself reserve only for Application Pools. For AppDomains, I prefer using the term 'restart', in order to avoid misconception. Based on this, restarting a AppDomain means starting over a given application with the newly added settings, such as refreshing the existing configuration. That happens within the boundaries of that sub-region of memory, called AppDomain, that ultimately lies within the process associated with a respective Application Pool. Those new settings may come from files such as
web.config,
machine.config,
global.asax,
Bin directory,
App_Code,
and there may be others.
AppDomain are isolated from each other, that makes total sense. If not so, if changes to a web.config, let's say, of application 1, requited recycle of the pool, all other applications assigned to that pool would get restarted, what was definitely not desired by Microsoft and by anyone else.
Summarizing my point,
Process (W3WP.exe)
AppDomain 1
AppDomain 2
AppDomain 3
AppDomain n
n = the number of assigned applications to the Application Pool managed by the given W3WP.exe
Processes are memory regions isolated from one another
AppDomains are sub-memory regions isolated from one another, within the same process
Global IIS settings changes may require Application Pool recycle (killing and starting a new Worker Process, W3WP.exe)
Application-wide settings changes AppDomains concerns, and they may get restarted after changes in some specific files such as the ones outline above
For further information, I recommend:
http://blogs.msdn.com/b/david.wang/archive/2006/03/12/thoughts-on-iis-configuration-changes-and-when-it-takes-effect.aspx
What causes an application pool in IIS to recycle?
http://blogs.msdn.com/b/tess/archive/2006/08/02/asp-net-case-study-lost-session-variables-and-appdomain-recycles.aspx
Regards from Brazil!
Take a look at this - that might explain it:
http://weblogs.asp.net/owscott/archive/2006/02/21/ASP.NET-v2.0-2D00-AppDomain-recycles_2C00_-more-common-than-before.aspx#440333
In general. What is called "first hit" on an ASP.NET Website is usually taking longer time, due to compilation, and creation of an AppDomain.
Whenever you deploy a site - make sure to use the "Publish Website" function in Visual Studio, to pre-compile your website. Then the "first hit" penalty is reduced. And remember to set the configuration to Release, and not Debug!
Recycle shuts down the process hosting the appdomain. You'll notice that the PID changes when you recycle it.
Unloading the AppDomin simply unloads all of the assemblies in the AppDomain, which can then be reused.
The important thing to remember is that once the CLR is loaded into a process, it can't be removed. So if you needed to do something as soon as the CLR is loaded, then simply unloading the AppDomain won't help, because the CLR won't be reloaded.
Also not that IIS isn't the only process which can host the AppDomain - any process can, and you don't always want to kill the whole process just to unload your assemblies.
If your pages are "updatable," they must be compiled before use. That means, yes, on first request the assemblies are loaded, compiled, and made ready for accessing. Whenever these files are changed (even some virus software can trigger this by changing the modified date of the files!), the appdomain gets recycled.
You can configure your web application to not be updatable. Everything gets compiled into DLLs, and you won't see any .ASPX or .CS files in the virtual directory. It makes your code harder to update (need to put some additional text on your webpage? Recompile time!), but it increases the availability of your web app.
However, this still won't prevent your web app from being recycled if any of the files are altered. For example, if you edit web.config, your appdomain will recycle even if its compiled.

Resources