Code reusability - App_Code or BIN or UserControls? - asp.net

I recently had a discussion on another forum with another developer and the topic was Code Reuse in ASP.NET. The stated scenario was that he needs to update code frequently on Production servers during server uptimes, and this results in Session getting reset for all users. He is avoiding putting shared code or classes into the App_Code folder or precompiled DLL's into the Bin folder because any updates will also refresh the Session.
The solution he has come up with is to put his shared code into UserControls and reference them wherever required. This enables him to update only the UserControl files which would be recompiled dynamically on next request without forcing a Session restart. Note that the Usercontrols are not intended to have any UI, they probably only house some business logic.
I tried to convince him against this because it felt intrinsically wrong to me - but I could not provide any hard facts to support my claim that this was a very bad way of doing things. The only thing I could think of is that it violates the principle of separation of business logic from UI. Am I grossly mistaken or are there concrete reasons why this should not be done? Links or examples would be helpful.
Note: Using out-of-process Session state is not an option at present, nor have they been able to decide on scheduled downtimes. Also, since this is a site under active development, they don't seem to be using any sort of professional deployment model yet.
Thanks in advance.
Edit: Additionally, it would be helpful if someone could clarify exactly why the Session restarts in the above mentioned cases.

It does seem like an unusual approach, and persistent session is the obvious answer. Assuming that reasons not to use persistent session are legitimate, sometime you just have to go with whatever works. I'd make a point of clearly documenting in the source files the unusual use of usercontrols and live with it.
To answer the why does session get reset edit. With in process session all the session data is in memory as part of your application. Various changes to the web site (e.g. web.config and others I don't recall off the top of my head) cause the application to restart wiping out all current state in your application. Persisting to SQL or the out of process session state server would allow the application to reset and lose any state without affecting the session data.

It sounds like the main problem is that he's updating production code too frequently. Other than that, UserControls seem like a perfectly reasonable place to put business logic, especially if you have a good naming convention for them or can put them in a common folder.

May i ask, why isn't out-of-process session state an option, really?
Since this guy seems to put in so much effort to get around this "problem", wouldn't he be better off looking at better solutions? out-of-process session state is the only good solution.

I'll agree with Dennis, there are really no issues moving from inproc to the state server. Not sure what your dev/deployment platforms are, but they should include a session state service - start that up, change your web.config, and the problem is solved.

it's a clever (and ugly) solution to a common problem
The main problem is the architecture of such system; the code that needs to be updated can be put on a different service outside his web app, his code behind can then call these services, and the services can be updated when needed without affecting the web app

Every base has been covered already, but I really hate bad practices like this. If the guy can't simply change to a state server to fix the problem that he has, then he doesn't really deserve the help. What would happen if he put his class in the root folder of the project and compiled it independently? Either way, I would think this guy is a bad developer for not thinking about scalability, and not planning for downtime. What I'm guessing is he doesn't have a development environment available. Tsk tsk tsk.
As an answer to your question, as stated by everyone else, put the code in a user control, and document well.

Related

Unwanted ASP.Net MVC3 server side caching

I'm working on an MVC3 app and I've come across an issue with objects being cached unintentionally.
My code is creating objects from calls to a separate custom business logic dll.
This business logic dll gets data from a database.
After I change data in the database, I'm still seeing the old data, even after closing my browser and re-running the application. It's not a browser caching issue because I can see it when I'm debugging in the development environment.
In development, if I stop the asp.net development server, then re-run the app, I get the new data.
In IIS, if I restart the website, I get the new data.
Any idea why asp.net is caching and re-using these objects, even after they have gone out of scope?
The business logic dll does have some caching built into it, so maybe that's the main issue. In that case, I guess the question is whether there is some way I can tell asp.net to wipe out the objects once the session is over.
There's no caching by default in ASP.NET MVC3, at least no caching of data. Make sure your IIS settings are correct and you don't accidentally use the OutputCacheAttribute.
As for caching in the business layer: I've seen at least three caching-related problems in the last two days. Keep in mind: Caching is tricky, and so are static variables. If it's not necessary, don't do it. Caching is extremely powerful, but it's also dangerous. That is also true for the beforementioned OutputCacheAttribute.
It sounds to me like you're creating your data context statically, rather than creating a new one and destroying it after ever request. This is a bad thing to do for a lot of reasons.
When you say that business layer has "some cacheing", what does that mean? How are you cacheing?

Which Has Better Performance - Configuration In AppSettings or Database?

I'm looking for feedback as to where I should store application configuration data and default text values that will have the best performance overall. For example, I've been sticking stuff like default URL values and the default text for error messages or application instructions inside the web.config, but now I'm wondering if that will scale....and if it's even the right thing to do in the first place.
As mentioned before, this really shouldn't matter - the settings, be they in the web.config or in a database, should be 'read-once' and then cached, so this really shouldn't matter.
I can almost guarantee that there will be other parts of your code much slower than this.
As a side note, and not performance related, but if you need to worry about site uptime, you can edit configuration in a database on the fly, but changing the web.config will cause an appdomain restart and subsequent loss of sessions.
If it's a single server setup (as opposed to a Web farm) store it in the Web.Config file. There is a new release of the Web Farm framework and you could check details for that type of scenario here:
http://weblogs.asp.net/scottgu/archive/2010/09/08/introducing-the-microsoft-web-farm-framework.aspx
If the database is on the same machine performance difference may be neglect-able. If you need to cross a wire to get to some database it's most likely slower then a directly accessible and not too large web.config.
I really would prefer keeping things simple here, just use the web.config. It probably is already getting cached in memory by some system component. If you feel it's too slow measure it and then perhaps go for a more complicated solution.
Having said that you could simply read in all configuration at application start-up and hold it in memory. This way any performance difference is mitigated to just the application's start-up time. You also get the added benefit of being able to validate the configuration files at start-up.
Not sure about your defaults but just ask yourself if they are environment specific and is it really something you want to change without recompilation. Being configuration files, what is the use case? Is some operations guy or developer going to set these defaults? Are you planning to document them? Are you going to make your application robust against whatever is configured?
Are these defaults going to be used on multiple environments/installations (used for localization for instance)? Then perhaps it's better to use a different and separate file which you can redeploy separately when needed.
How often are the settings going to change?
If they never change, you can probably put them in web.config, and configure IIS so that it doesn't monitor the file for changes. That will impose a small startup penalty, but after that there should be no performance penalty.
But honestly, there are probably dozens of other places to improve before you start worrying about this - remember, "Premature Optimization is the root of all evil" :)

ASP.NET Session Mix-up using StateServer (SCARY!)

We store two objects in session. Somehow, one of the objects from another user got loaded into a different user's session. The user should have had no access to this particular data, and as soon as they saw it they knew something was very wrong.
We have visual proof of the data that was presented to him, and there is certainly no way it could've happened unless the sessions got mixed up. This is a very scary situation which we can not figure out (we can not reproduce it). The only answer for us is to blame ASP.NET StateServer for mixing the session variables up, which is completely unacceptable and puts us in a bad position.
Our applications are ASP.NET 2.0 apps running on Windows Server 2003 with IIS6, using the StateServer cookieless="false" session mode and FormsAuthentication.
Has anybody else had this problem? How can we resolve it?
We ran into this exact issue in my previous company and took 3 weeks to debug it. ASP.NET was giving a user someone else's session state. It was really impossible to duplicate in a debug environment.
The fix when we found it was just something in web.config. I don't fully remember it, so I spent some time googling. I believe the issue had something to do with output caching. Take a look at this article under "Sessions and Output Caching".
http://download.microsoft.com/download/3/a/7/3a7fa450-1f33-41f7-9e6d-3aa95b5a6aea/MSDNMagazineJuly2006en-us.chm (the article is titled Keep Sites Running Smoothly By Avoiding These 10 Common ASP.NET Pitfalls by Jeff Prosise in July 2006 edition of MSDN magazine)
If that sounds like your scenario, then the fix might just be disabling the enableKernelOutputCache option in web.config.
Good luck.
Look for bugs in your own code first - this is by far the most likely explanation. E.g. using static fields or other shared memory such as the ASP.NET cache for user-specific data.
Possible answer - similar isue reported using cookieless session state.
session showing something wrong
Edit - Added
Another possible answer:
An ASP.NET page is stored in the HTTP.sys kernel cache in IIS 6.0 when the ASP.NET page generates an HTTP header that contains a Set-Cookie response
How many times did it occur? Did you check for users using browser back or sending links to each other with session ids?
One way to check for sure about State Server bug is to switch to another session manager, fallback to in-proc if you can or use SQL Server but would be better to find a way to reproduce the bug it first so you could test it.
Could the two crossed users both be using the same cacheing proxy? If so, then one user might see data that was cached for another user if the URLs matched, especially if the proxy isn't well behaved.
Wasn't this the main problem with the Google Web Accelerator project (now discontinued)?
Had this problem, turned out to be an OutputCache attribute on a partial view.

Single ASP.net site with Multiple Instances & web.configs

We have a legacy ASP.net powered site running on a IIS server, the site was developed by a central team and is used by multiple customers. Each customer however has their own copy of the site's aspx files plus a web.config file. This is causing problems as changes made by well meaning support engineers to the copies of the source aspx files are not being folded back into the central source, so our code base is diverging. Our current folder structure looks something like:
OurApp/Source aspx & default web.config
Customer1/Source aspx & web.config
Customer2/Source aspx & web.config
Customer3/Source aspx & web.config
Customer4/Source aspx & web.config
...
This is something I'd like to change to each customer having just a customised web.config file and all the customers sharing a common set of source files. So something like:
OurApp/Source aspx & default web.config
Customer1/web.config
Customer2/web.config
Customer3/web.config
Customer4/web.config
...
So my question is, how do I set this up? I'm new to ASP.net and IIS as I usually use php and apache at home but we use ASP.net and ISS here at work.
Source control is used and I intend to retrain the support engineers but is there any way to avoid having multiple copies of the source aspx files? I hate that sort of duplication!
If you're dead-set on the single app instance, you can accomplish what you're after using a custom ConfigurationSection in your single web.config. For the basics, see:
http://haacked.com/archive/2007/03/12/custom-configuration-sections-in-3-easy-steps.aspx
http://msdn.microsoft.com/en-us/library/2tw134k3.aspx
Example XML might be:
<YourCustomConfigSection>
<Customers>
<Customer Name="Customer1" SomeSetting="A" Another="1" />
<Customer Name="Customer2" SomeSetting="B" Another="2" />
<Customer Name="Customer3" SomeSetting="C" Another="3" />
</Customers>
</YourCustomConfigSection>
Now in your ConfigSection Properties, expose Name, SomeSetting, and Another. When the Property is accessed or set, use a condition (request domain or something else that uniquely identifies the Customer) to decide which to use.
With the proper implementation, the app developers don't need to be aware of what's going on behind the scenes. They just use CustomSettings.Settings.SomeSetting and don't worry about which Customer is accessing the app.
I know it might seem annoying, but the duplication is actually a good thing. The problem here is with your process, not with the way the systems are setup.
Keeping the sites separate is actually a good thing. Whilst it looks like "duplication" it's actually not. It's separation. Making changes in the production code by your support engineers should be actively discouraged.
You should be looking at changing your process to change once deploy everywhere. This will make everything a lot easier for you in the long run.
To actually answer your question, the answer is no, you can't do it. The reason is that web.config isn't designed to store user level settings, it's designed to store per application instance settings. In your case, you need an application instance per user which means separate config files.
For your system to work, you need to be able to preemptively tell the application which config file to use, which isn't possible without some sort of input from the user.
Use an external source control application and keep rolling out updates as required.
It isn't really a good idea to let your live site be updated by support engineers in real time anyway.
Depending on what is actually in the web config, and what settings differ between customers, you could opt to use a single web config, and store other customer specific configuration options in a database or some other custom xml/text file. As long as the specific customer settings in the web.config don't have to do anything with how IIS operates, and you are just using it to store values, then this solution might work out well for you.
Thank you all again for your answers. After reading through them and having a think what I think I will do is leave the multiple instances alone for now and I will try to improve our update process first. then I will develop a new version of the application that has the user configuration information in the database layer and then pick the user based on the request domain or URL as someone suggested. That way I can have a single application instance supporting multiple different client configurations cleanly.
As most of the client configuration data is really presentation or data source related, nothing complicated. I think we ended up with multiple application instances mostly because the original programmer hadn't been expecting multiple customers and didn't design for that so when someone came along later and added a second customer they just duplicated the application which is wasteful as each instance is about 99.99% identical to the original.
I am implementing this as we speak.
In the main web.config, I have 1 item per installation. It points me toward the custom config file I built for each client (and toward the custom masterpage, css, images, etc).
Using WebConfigurationManager.OpenWebConfiguration, I open the new webconfigs in their subdirectories. I determine which one to use by using System.Web.HttpContext.Current.Request.Url.OriginalString, and determining the uRL that called me. Based on that URL, I know which web.config to use.
From that point forward the clients all use the same codebase. They have their own databases too.
The idea of having to update 30-40 installations when we make an update scares the death out of me. We do not want to support 30-40 codebases, so there won't be customization beyond the master page, css, and images.
I wrote a custom class lib that knows how to switch to the proper webconfig, and read the custom section I built with all our settings.
The only issue I have now is the FormsAuthentication Cookie. I need to be able to switch that as well. Unfortunately, the property for the name is read only
If I understand correctly, it sounds like you have multiple deployments (one for each client) where the only difference is the web.config, right?
First off, although I don't know your unique situation, I would generally urge you to stay with separate installs. It usually allows much more flexibility. Off the top of my head: are you ever going to have customizations, or different clients running different versions? Are you sure? The easiest way to stay flexible here is to keep going with separate installs.
In my opinion, it isn't ugly at all if your practices are aligned properly. Based on some things you mentioned, you have trouble in that area - obviously, possible source control buy-in/training issues. But you are aware of that. I would also take a hard look at your deployment procedures and so on. I have a feeling you might have further issues in that area, and I mean absolutely no offense.
That said, let's say you want to move forward with this.
You didn't say whether all the clients share a single common database, but I'm thinking no, since designing that type of system is often not worth the extra complexity (which can be severe in systems of any size) so people often opt to keep them separate.
What that means is that you have store your connection string somewhere. Usually that would be web.config... So that seems to break our plan.
Really, the apparent elegance of this situation is almost always wildly offset by the challenges it introduces. If I thought about it hard enough, I could maybe find a way around this by introducing another database that intelligently manages connection strings or maybe delving into keeping all your login info directly in web.config (which is possible but... not ideal), however my gut says the work will be wasted because some day you will end up going back to how you're doing it now.
Also: changing code directly in production is obviously not the best practice here. But you if you are on a monolithic shared platform with any amount of traffic, that can never ever ever happen. Food for thought.
Let me know if I'm missing something!

Can ASP.NET 3.5 Web Application Projects be Extended or Patched "in Flight"?

In building an ASP.NET 3.5 WAP, I'm always frustrated by the feeling that no matter how I "isolate" or "encapsulate" bits of logic or UI I'm still going to bring down the whole site any time I need to update a single line of code. I may be misunderstanding how ASP.NET handles changes in the "bin" directory, but given the number of "why is my AppDomain unloading?" messages in the various groups this still seems like something to avoid.
Does anyone have any guidance and/or frameworks to truly modularize an ASP.NET 3.5 WAP so that logic and pages can be added/updated "in flight"? I Googled System.AddIn a bit, but it seems to be focused on WPF applications.
Thanks for your help!
James White
This is really hard to achieve since .NET doesn't support unloading a type that has been loaded into the app domain.
One way to do it is playing around with app-domains, or having WCF do it for you.
Another would be implementing ayende's hod code swapping.
A third way would be putting logic in the dynamically compiled part (the ASPX). However the app will restart after a configurable amount of changes.
Use two or more servers. When you need to upgrade, take one down, upgrade it, bring it up, take the other one down, upgrade it, bring it up.
It takes a bit of effort to be able to do this - having both versions running at the same time - as database changes etc can be tricky. But the same effort also pays off in being able to roll changes back, perhaps host just a few users on an "experimental" server etc. Not to mention horizontal scaling being a good thing in general :)
You can take a different approach here, which is to make it that an AppDomain restart doesn't affect usability of the site.
To do that, move session out of process, or stop relying on session entirely.
If you do this, an appdomain restart isn't a big deal, and you are prepping your application for easier scalability across clusters if you ever get to that point.
Just an added thought, but I bet that was what that whole "COM+" bit allowed (save for shared hosts). Breaking logic down into little stateless sausage factories probably allowed for smooth fix-in-flight operations.

Categories

Resources