Is there a bug with this design? - asp.net

I'm completing a feature that was started by a previous developer. I notice that he's loading settings from the db in the Global.asax Application_Start method and puts the settings into HttpContext.Current.Application["SettingName"].
In development this works fine on my machine. If I'm not mistaken though this looks like in production it's going to load the data once when the application starts for the first user but settings will not be available to the application for any subsequent user.
Can someone please confirm or deny my suspicions?

The HttpContext.Current.Application["SettingName"] is a static property. It will be available to the next subsequent users as well. But you can not change it that easy, especial if you use web garden.
You can read more details here: Using static variables instead of Application state in ASP.NET
I do not know how the design is, but you can use a simple static dictionary for the same... of direct read from the database your parameters, or from web.config.

I generally wouldn't touch the HttpContext in Application_Start. In fact, I don't think IIS's Integrated Pipeline will even let you do that.
With integrated pipeline, Application_Start could get fired before any requests even hit the server, such as IIS 8's Application Initialization.

I recommend that you place the settings in the web.config file and use the ConfigurationManager object to read those settings. This is a lot simpler, as there is no need to store them in the HttpContext.
e.g.
<configuration>
<appSettings>
<add key="SettingName" value="SettingValue" />
</appSettings>
</configuration>
Doing this means the settings will be available to the entire ASP.NET application - there is no need to store them in the HttpContext.
There is a caveat that when you update the web.config file the application pool for the ASP.NET site will be recycled. But the consequences of this all depend on what that site is doing with, for example, session state and caching. Recylcing the application pool will reset those, but that's for another question.....
EDIT:
Based on the comments, it sounds like session state will help you here. With session state, you can store the user specific settings so that they do not interfere with other users.

Related

Set up RAMMFAR for certain paths only

I have an ASP.NET 4.5 MVC app. I don't want to set RAMMFAR (runAllManagedModulesForAllRequests) because that would needlessly send requests for static resources through the ASP.NET pipeline; however I do want all requests which begin with the path /Download/ to run through the ASP.NET routing pipeline, regardless of extension. This way I can route them to a Controller and serve dynamically generated resources.
How can this be done? I do not have access to IIS settings but hopefully there is a way to do this through web.config.
The RAMMFAR setting is per application. You'd have to create a separate IIS applications if you want different parts of the site to have different settings, but unfortunately you state this is not an option for you.
I two have two side notes though:
Are you sure you even need RAMMFAR? I think that when using IIS 7.5 and newer it's very rarely needed because IIS and ASP.NET can pretty much handle managed/native requests correctly.
Have you identified this as an actual problem to always have it enabled? Undoubtedly RAMMFAR will make things slower, but the question is whether it's causing a measurable effect in your app. Even if a static file does go through some managed code, the final processing of the file is handled back in native code. So there's a bit of extra work to go "through" the ASP.NET managed pipeline, but once that's done it's back to native IIS/Windows code.
It is surprising to see that this hasn't been answered in Stack Overflow for long time.
As you've mentioned - runAllManagedModulesForAllRequests is not required when you just need to capture all requests for a particular path in your site.
You can specify a path pattern which should be send to MVC handlers as shown below
<add name="DynamicDownloadHandler" path="/download/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
Above pattern will capture both extensionless and paths with extension.
A sample implementation for serving dynamic images in MVC is linked here.

Disabling Classic ASP without disabling ASP.NET on IIS

BTW this is not something I am want but is a requirement I must follow. My requirement is to create a user interface that will allow users to disable Classic ASP while allowing ASP.NET 1-4 applications run. Can anyone think of a use case were a user would want to do this?
Sure, if you were a web-host offering partial access to a webserver through an application that emulated some of the relevant IIS options, then not only would customers not want the added risk of unneeded script/executable systems running, but you wouldn't either, so you'd want it turned off unless they went in and explicitly turned it on because they needed it.
Indeed, software for this use-case already exists.
Jon's comments about reducing a site's attack surface by removing unwanted features is very valid. You should ideally just run what you need and no more.
There are a number of ready made commercial solutions to this problem such as Plesk, but they may provide too much functionality for your needs.
You could write your own functionality:
If this is IIS6 then you should take a look at the ADSI API which is surfaced via the System.DirectoryServices namespace:
Using System.DirectoryServices to Configure IIS
To enable/disable scriptmaps you need to manipulate the ScriptMaps metabase property for a site:
ScriptMaps Metabase Property (IIS 6.0)
If this is IIS7 then take a look at the Microsoft.Web.Administration managed API. In IIS7 you want to manipulate the handler mappings for a site:
Handlers <handlers> - IIS.NET
In all cases, the user must be a member of the machine's Administrators group.

Sharing authentication between two web applications

I have a base web site (Asp.net WebForms application) running under ie.
http://localhost:90/
Then I created a new (this time Asp.net MVC) application and added it under
http://localhost:90/mvc/
but not just as a simple virtual folder, but as an application folder by defining a different application pool to run it, compared to the parent application.
Since browsers can't know that there are two different application basically on the same domain it would work like:
user accesses http://localhost:90/
parent app redirects the user to forms authentication screen
user successfully logs in
parent web adds an authentication cookie
user accesses http://localhost:90/mvc
browser attaches the same cookie from parent app
Is it possible that I authenticate the user based on this same cookie? I would configure my MVC application to login redirect to parent app to have a shared authentication screen. But I'd like to know who authenticated and work from that point on.
I've read something about sharing the same system.web/machineKey values to provide this kind of functionality, but I would like some real world examples.
I'm aware that these two applications will not be able to share Session state and that's not a problem, because I don't want them to. All I want is a kind of single login (SSO/SSS)
Is this possible? How?
Important
I've read other questions/answers about this, but they are either asking about cross-domain/cross-server etc. This one is on the same IIS web site.
I found it myself.
This is the article on MSDN that talks exactly about this scenario. I decided to keep this question anyway for anyone that would be chasing the same information some time later.
MSDN: Forms Authentication Across Applications
In brief
You have to configure machine keys in web.config of both applications so they match hence they'll be able to decode data that the other party generated. And that's the whole trick. MSDN article explains this in great detail including how to generate those keys.
If in case anyone is still not able to share the keys use
compatibilityMode="Framework20SP1"
<machineKey validationKey="same key all over"
decryptionKey="same key all over"
validation="SHA1" decryption="AES"
compatibilityMode="Framework20SP1"/>

How to prevent having to re-login to ASP.NET web apps after a code change

I dislike it when I lose the session state of my ASP.NET web app when changing code.
Losing the session state means I have to log in over and over again. It's annoying.
Is there anyway I can reconfigure my app so that I can make changes to code and not have to re-authenticate to view those changes?
(I know that changing .ASPX files does this fine. My concern is over App_Code and Bin compiled code.)
Unfortunately changes in the web.config or in dll's in the bin folder will cause an application reload and there is nothing you can do about it, AFAIK.
I wonder what will happen if you will store session state in StateServer. Maybe it will work ( I will be surprised if it does).
If you are in a developer environment you can try disabling logging into the site, or when the site checks for authentication just return your default authentication. For production, a StateServer will help as Igal pointed out.
One last option, store the login information in Session, but as a backup to that use a login table in your database to be able to restore a user's authentication status from a cookie. Obviously, consider security implications.
By changing your StateServer to use your machine (enabling the ASP.NET State Service), you won't lose your login.

Can we create an application with its own Web.config and Forms Authentication section inside another application using Forms Authentication?

I have an application that uses Forms Authentication to authenticate one type of user. There is a section in this application that needs to be authenticated for another type of user using a different table in the database. The problem happens if the second type of user's session times out, she is taken to the login page defined in the Forms Authentication section of the main Web.Config instead of the login page for the second type of user. I am looking for solutions to this problem. One idea is to create an application in IIS for the section and create a Web.Config for the folder and add another Forms Authentication section. In my experiments, it seems this doesn't work. Am I missing something obvious? Any insights?
IIRC, the authentication works per folder. So you should be able to do it if all of the pages that require the 2nd type of authentication live in a specific sub-folder with it's own config.
Not 100% sure on this, though, so if someone more knowledgeable can contradict me I'll just delete the response.
You may need to double check me on the syntax, but the top level web.config can have any number of tags.
<location>...</location>
Inside you can specify separate config parameters for whatever folder/file you want. Look here for a reference.
EDIT: Apoligies, I neglected to format the code properly
You cannot have an <authentication> section inside of a <location> tag, so you must have the subfolder set up as an IIS (and ASP.NET) application of it's own. So, you should be able to run the subsection on it's own.
I think 500.19 is the "can't read or parse web.config" error - does it have details? You may need to turn on remote errors (or check Event Viewer) to see them. If you're still having issues, post a snippet of web.config.
As an aside - I've never been a fan of nested apps, and would probably prefer having your normal Login.aspx page handle it either with as a MemberOf or perhaps redirecting to a SpecialUserLogin.aspx or something. Nested apps are a PITA to setup and test, IME (for instance - I don't think you can even get it working under Cassini - though you can do 2 separate projects for it, and combine when you deploy).
Yes you can. The Web.config files have a tree-like inheriting arhitecture with override capabilities. Meaning you can modify the settings inside a sub-folder by placing a web.config file there and specifying different configuration settings.
The way I understand this problem, you have two solutions and the first is to look at Roles and the whole Provider Model would be a great place to start. Otherwise, the best bet would be to separate the application into two parts, breaking out the second user type area and then including it back into the main project via a Virtual Directory. Just remember that Virtual Directories inherit their permissions from the parent directories web.config, so you will need to use the <Location>tags to remove authentication for the virtual directory and then within the virtual directories web.config define your new forms authentication. This works well if you need Windows Authentication (NTLM) under Forms Authentication.

Resources