Thursday, October 16, 2008

Great post by Omar Al Zabir on regards best practices for creating websites in IIS 6.

This post will demonstrate you step by step how to make your website more scalability and cachable.

http://msmvps.com/blogs/omar/archive/2008/10/04/best-practices-for-creating-websites-in-iis-6-0.aspx

Posted by: Eran Nachum (c)
Post Date: 10/16/2008 10:41:05 AM (Jerusalem Standard Time, UTC+02:00)
Disclaimer | | Trackback   #
 Tuesday, March 25, 2008

This is quite strange story... but I decided to publish this post because I didn't find any proper solution anywhere; and I mean it ANYWHERE!

It begins like that: I am running an asp.net 2.0 web application that as part of its work, it has to communicate 3rd party assembly, which suppose to retrieve some validation data. Until here everything is just fine right?

In order to invoke the 3rd party service (using an API of course), there is a need to install a X509Cerificate with 'secret' password and to install it on the server that runs the web application. After doing it you must  impersonate the ASP.NET process with the logged-in user that installed the certificate in order to 'grant' this user permission (administrator) to the current context of the web application.

Note: the user credentials will be kept in the web application web.config encrypted of course.

When running this application in my dev box, everything was working just fine, but when done with unit testing and was ready to QA, only when the user that installed the X509Certificate was logged in to the system (windows) the access to this specific certificate could be done. When the user was logged off, the Initialize method that initializes the certificate, couldn't find it in the CurrentUserStore:

public void Initialize(some parameters...)
{
   X509CertificateCollection certificates;
   X509CertificateStore store = X509CertificateStore.CurrentUserStore("My");
   
   store.Open();
   certificates = store.FindCertificateBySubjectName("<subject>");
   if (certificates.Count <= 0)
   {
      throw new Exception("<message>"));
   }
}

I admit that I didn't have any clue of how solving this acute problem, which of course stuck all the process of dev.

After consulting with some colleagues, we decided to try a 'detour solution', that will raise the user up into the system (will keep it alive, unlike doing log off to the user that terminates it from the OS).

Finally the solution (what you've waited for of course): 

We created a blank window service (with an installer) that actually does nothing, complied it and installed it in the QA server. Now here is the catch: First, the window service's startup type is set to Automatically (will be started always when the OS is up). secondly we adjusted the service's log on to a specific account that held the credentials of the user that installed the certificate of course. The purpose of this action is to keep this user up all time in order let our 3rd party application find its certificate in its store.

Outcome - it is working smoothly like magic. We can continue working...

Posted by: Eran Nachum (c)
Post Date: 3/25/2008 8:49:00 PM (Jerusalem Standard Time, UTC+02:00)
Disclaimer | | Trackback   #
 Tuesday, December 04, 2007

This post comes as a continues to the previous one. I thought about some insights regarding this issue and in the bottom line, there are some significant disadvantages that I could think about:

  1. Get from the starter point that web application is stateless, this is the most important disadvantage - you cannot rely on that admit it or not.
  2. What about performance - like the former post, this kind of alive (web) service will grab a thread permanently from the application pool and we'll use it - this thing damage in a matter of time the performance.
  3. What about IIS reset action. If being done, the process will be 'dead' and this thing is worth to nothing because we can't rely on anyone to check if it alive.

The main conclusion:

Don't count on web application in order to run scheduled tasks - you can't rely on it in 100% (however you have tools that meant to monitor it).

I takes Ken Egozi's comment of creating a scheduled task (instead of windows service) that will do the scheduled job (I going to keep my local machine alive forever I think ;))

Posted by: Eran Nachum (c)
Post Date: 12/4/2007 7:00:48 PM (Jerusalem Standard Time, UTC+02:00)
Disclaimer | | Trackback   #
 Monday, September 24, 2007

As I posted in the last post, I didn't have much time to update my blog last month (even most of this month), so I hope I could catch up these days and post some more about the on going issues that comes up.

Last month, a gut named Roni Schuetz send me an email regarding my post about Maintaining Data over Multi-Servers (Load Balancing on Web Farm) (direct link here).
Roni is the creator of a project named, Shared Cache which supplies high-performance, distributed memory object caching system, generic in nature, but intended to speeding up dynamic web and / or win applications by alleviating database load. He suggested me to use his project regarding maintaining cached data between multiple servers and I acceded testing it.

By Roni's documentation and project usage explanations the project is friendly usable and for a free-to-use-software I think it is highly recomended using it (or at least testing it).

Unfortunatly (or not), my company (IDT Global) has purchased (an expensive and also a great one) tool called ScaleOut SessionState In order to maintain session data over multiplae servers.

So, if you have an answer regarding this issue or just want to read about it, you can try Roni's indeXus.Net Shared Cache here.

Posted by: Eran Nachum (c)
Post Date: 9/24/2007 10:15:21 AM (Jerusalem Standard Time, UTC+02:00)
Disclaimer | | Trackback   #
 Tuesday, July 10, 2007

I am working against 3rd level party assembly in my current web application. I need to send US address information to this assembly and to retrieve an answer whether this address is exist or not. This assembly requires validation against X.509 certificate (to ensure that only permited client could use the 3rd level's services), which is installed on the server that runs the application (in dev environment this is my local PC).
More details about it here.

The problem: In order to authenticate against this certificate, the process that runs the application need to 'hold' sufficient credentials in order to get an access to the certificate and to do the authentication. Here comes our problem; when trying to access this certificate through the asp.net application, we run into a problem - It's impossible, because the process that runs the web application is ASPNET and doesn't has the needed credentials in order to authenticate the certificate and get the info from the 3rd level.

Suggested solutions:

  1. Credentials. Read the credentials from the web.config (username, password and domain) and impersonate the user using these credentials. This will 'save' the impersonated user all over the impersonation context (System.Security.Principal.WindowsImpersonationContext) and the authenicate action against the certificate will be done using this credentials. One more important thing, to ensure this data protected, encrypt it before puting it into the web.config.
  2. I thought about IIS Application Pool. This is a great feature that came up in IIS 6.0, which enables you the ability of creating one or more applications and allows us to configure a level of isolation between different Web applications. You can set the identity of an application pool which will be the account under which the application pool's worker process runs. So I thought to set it over there, but I had one big problem, an IIS 5 was installed on the production server and it is not a dedicated server. (More details about application pool here).
  3. Host .NET component in COM+. This is the third solution and the best for me at the current circumstances; Because I am working with a several applications (assemblies) I want to host the component that validates the user against the 3rd level party, this will give me a unified behavoir for all the applications while doing this action (Instead of setting these properties in web.config file of each web application we want to use {solution 1, remember?}). In other words, I'll set the username and password on the COM+ component just once in order to grant the process that runs this component the right and sufficient credentials. .NET provides a way to host your .NET components inside COM+ environment. All the functionality you need to write a COM+ aware component in .NET can be found in System.EnterpriseServices namespace.

So how we do it (hosting .NET assembly in COM+)?

Take a look on this code:

using System;
using System.Collections.Generic;
using System.Text;
using System.EnterpriseServices;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;

namespace ComPlusTest
{
    [Transaction(TransactionOption.Required),
        ObjectPooling(MinPoolSize=2, MaxPoolSize=5, CreationTimeout=20000),
        ComVisible(true)]
    public class TestClass : ServicedComponent
    {
        protected override void Activate()
        {
            base.Activate();
            DoSomeAction(Action activate)
        }

        protected override void Deactivate()
        {
            base.Deactivate();
            DoSomeAction(Action deactivate)
        }

        protected override bool CanBePooled()
        {
            DoSomeAction(Action pooled)
            return base.CanBePooled();
        }

        public void ValidateAddress(string address)
        {
            try
            {
               // Do the validation against the 3rd party
               ContextUtil.SetComplete();
            }
            catch(Exception ex)
            {
               // Handle exception
               ContextUtil.SetAbort();
            }
        }

        [AutoComplete()]
        public void JustAction()
        {
            DoSomeAction(Action simpleAction);
        }

        private void DoSomeAction(Action act)
        {
            // Do the action
        }
    }
}

Lets dissect it:

  1. Firstable you can see that the class is derived from ServicesComponent (which sits in the System.EnterpriseServices namespace). I marked our TestClass with some attributes. The first one in Transaction; The values for this attribute are same as in traditional VB/VC++ development i.e. Required, RequiresNew, Supported etc. MinPoolSize and MaxPoolSize specifies values for minimum and maximum object instances. The ComVisible attribute must be set to true to give the accessibility of an individual managed type or member, or of all types within an assembly, to COM (I spent lots of time trying to figure out some exceptions that I had while overriding the ServicesComponent class).
  2. the class is marked to require a transaction each method will execute in a transaction (existing or new). Once the ValidateAddress has been executed we need to either commit or rollback the transaction. This is done via static methods of ContextUtil class. The method SetComplete is used to commit a transaction where as SetAbort is used to rollback a transaction.
  3. Just for example, I defined a methid called JustAction. This method is marked with an attribute AutoComplete which means that once the method execution is over the transaction is automatically committed (equivalent to ContextUtil.SetComplete). In case of any error the transaction will be rolled back (equivalent to ContextUtil.SetAbort).
  4. Overrided Activate, Deactivate and CanBePooled methods are just for testing (in order to observe the flow behavior).

Now, you have to sign your assembly with a strong name and to add the following attributes to the AssemblyInfo class of your project:

[assembly: ApplicationName("ComPlusTest")]
[assembly: ApplicationActivation(ActivationOption.Library)]
[assembly: AssemblyKeyFileAttribute("ComPlusKey.pfx")]

Posted by: Eran Nachum (c)
Post Date: 7/10/2007 4:49:24 PM (Jerusalem Standard Time, UTC+02:00)
Disclaimer | | Trackback   #
 Wednesday, June 13, 2007

I know that I am a big fan of Microsoft products and technologhy, but I read today the Safari (from Apple) is ready to download.

Despite this version is still a beta, you can download it to your PC and start playing with it.

I downloaded it just to get the feel impression of it and also to has an idea how my web applications are being showed there... (good for cross browsers suitabilities). And it's nice...

Download is here.

Posted by: Eran Nachum (c)
Post Date: 6/13/2007 8:39:59 AM (Jerusalem Standard Time, UTC+02:00)
Disclaimer | | Trackback   #
 Tuesday, May 29, 2007

After doing great usage with CAPTCHA in my site (when adding comments - if you didn't try it I am inviting you to give it a try and add some comments after reading this post...), I decided to give some words about it...

Some definitions...
a CAPTCHA is a type of challenge-response test used in computing to determine whether the user is human, aka "Completely Automated Public Turing test to tell Computers and Humans Apart". A CAPTCHA involves one computer (a server) which asks a user to complete a test. While the computer is able to generate and grade the test, it is not able to solve the test on its own. Because computers are unable to solve the CAPTCHA, any user entering a correct solution is presumed to be human.

There are several approaches to this CAPTCHA mechanism, that comes to supply the same idea of effect (to differ a human user from a computer user of course), like:
- Carnegie Mellon's PIX CAPTCHA, which the user here sees few images and need to differ which one is exceptional.
- Oli Warner's KittenAuth, the user here needs to select all animals of specific speices in the proposed images.
- Microsoft's Asirra, quite similar to KittenAuth, but works under larger amount of images.

Some issues that are important in order of using CAPTCHA in your web site:

  • You must dock the CAPTCHA image/s in a non dominant place in your web site - think about it, the CAPTCHA mechanism is comes to help you to avoid bots, not to take a central place in your site.
  • The CAPTCHA image/s supposed to has as much as small weight (something like between 4 to 8 kb), the site should not be affected from the CAPTCHA image/s creation. I'd rather creating the CAPTCHA image/s using HttpHandler that display the image/s from an outside mechanism.
  • The area of the image/s should be appropriate to the site isuue. Images of cats should not be appropriate to a government site for example, therefore select the image/s properly.
  • Store the CAPTCHA in a safe place and name them in appropriate names in order to use it properly.

OK, what about some implementation? There are a lot of ways to implements this algorithm, which is not so complex. You can find a lot of written open source small application that implements this CAPTCHA mechanism.

In the web application that I am working on at work, we saves all distorted images in a DB (and its images' values of course) and grabs it randomally on each request of the specific page that holds the CAPTCHA. The distorted image is shown to the user and its value is stored in the page viewstate (which is also encripted of course).
After that user enters her input, that value is being validated against the distorted image's value and if it's correct, moves on...

Do you have more suggestions of CAPTCHA implemetations?

Posted by: Eran Nachum (c)
Post Date: 5/29/2007 8:14:09 AM (Jerusalem Standard Time, UTC+02:00)
Disclaimer | | Trackback   #
 Wednesday, April 11, 2007

Hello!

Some intro:
I am starting to migrate a classic asp web application (quite complicated) to .NET 2.0 environment and in the begining (of course) I am starting to learn the functionality of the existing web app.

This morning I came to work and started to rrun the asp web app, but my IIS (5.0) seemed to be dead. I couldn't run anything, even the localhost help page to get some information.

I disabled the "Show friendly HTTP error messages" from the explorer advanced options, and | got this messgae: "The server has encountered an error while loading an application during the processing of your request" - Interesting...

After doing some actions in the IIS, I succeeded solving the problem myself, I just changed the application protection to Low in the virtual directory folder properties.

Some info:
The Application Protection drop-down determines if this IIS Application is to be isolated in its own process, pooled with other apps, or in-process with IIS. This feature comes to give us the ability of isolating applications, configuring them to run in a process (memory space) that is separate from the Web server and other applications. You can configure applications to have one of three levels of application protection: Low, Medium, High.

Another thing is: The application protection determines how memory resources are allocated for ASP pages:

  • Low (IIS Process): this level runs ASP pages using the same resources as the web service. The advantage of the low level is that you are given the most permissions and access. The disadvantage is that if the ASP service fails, the web service will be impacted as well.
  • Medium (Pooled): this level allocates a pool of memory resources used by all ASP pages. The advantage of the medium level is that you control the amount of resources allocated. In addition, if an ASP page causes the ASP service to fail, it does not affect the web service. The disadvantage is that if one site causes the ASP service to fail, all of the ASP pages will fail.
  • High (Isolated): this level allocates a specific amount of memory resources for each ASP application. The advantage to the high level is that if an ASP page causes the ASP service to fail, only that specific site will fail and not the other sites. The disadvantage is that additional resources are used by each individual application pool.

Hope I helped someone...

Posted by: Eran Nachum (c)
Post Date: 4/11/2007 10:34:41 AM (Jerusalem Standard Time, UTC+02:00)
Disclaimer | | Trackback   #
 Thursday, December 28, 2006

Some of the impovments with that service pack are:

1. Refactoring performance in ASP.NET WebSites projects like:
    Before determining if an .aspx page should be loaded, the refactoring operation will:

      Perform a lexical search on the element that is being refactored to determine if it exists in an .aspx page.
      •

Determine if a reference is accessible from the current scope.

2. Web Site Projects and Web Application Projects general issues:
    The Web Applications project system does not detect missing web.config files. Adding a control that requires configuration information will cause a false folder to appear in Solution Explorer. The workaround is to add a web.config file manually before you add any controls to a Web Application project.

   Web Application projects that contain subprojects that reference controls in the root project may hang the IDE.

   If a Web site solution that contains .pdb and .xml files is added to TFS source control, the .pdb files and .xml files may not be added correctly.

   Visual Studio will leak memory when you operate a Wizard inside a View inside a Multiview. The workaround is to save the solution and then restart Visual Studio.

   Changes to the bin folder in Web site and Web Application projects can cause Visual Studio to create a shadow copy of the entire bin folder. This copying can slow the performance of Visual Studio and consume disk space.

   If your page and user controls exist in different namespaces that are under the same root namespace, the generated code will not compile because the namespace that the designer creates for the declaration of the user control inside the page is wrong. The workaround is to delete the declaration from the designer file and then put it in the code-behind file. Once it is moved to the code-behind file, it will remain there unaltered even if you change the page.

You can download it by pressing this link: http://www.microsoft.com/downloads/details.aspx?familyid=BB4A75AB-E2D4-4C96-B39D-37BAF6B5B1DC&displaylang=en

Posted by: Eran Nachum (c)
Post Date: 12/28/2006 12:29:42 PM (Jerusalem Standard Time, UTC+02:00)
Disclaimer | | Trackback   #
 Thursday, November 23, 2006

Hey guys how are you?

After long conversation with my work colleague, I thought that I need to sharpen the evidences about Application Domains - aka AppDomain.

By .NET environment, the concept of an application domain, or AppDomain known as a process. The AppDomain is both a container and a boundary. The .NET runtime uses an AppDomain as a container for code and data, just like the operating system uses a process as a container for code and data. As the operating system uses a process to isolate misbehaving code, the .NET runtime uses an AppDomain to isolate code inside of a secure boundary.

An AppDomain belongs to only a single process, but single process can hold multiple AppDomains. An AppDomain is relatively cheap to create (compared to a process), and has relatively less overhead to maintain than a process. For these reasons, an AppDomain is a great solution for the ISP who is hosting hundreds of applications. Each application can exist inside an isolated AppDomain, and many of these AppDomains can exist inside of a single process – a cost savings.

Lets take an example from the REAL life:
Assume that you had created 2 ASP.NET aplpications in the same server, what will happen intior the system?

Firstable, the ASP.NET process that runs the web application will run both the applications (you can find the process name in the task manager as aspnet_wp.exe in Windows XP or as w3wp.exe in Windows 2003. Each application will have its own AppDomain including its Cache, Application, and Session objects.
BUT, the code of the same application runs under the same process!

What about static members or shared classes? In this case, each ApDomain will have its own copy of the static members (fields), but of course, the data and code is not shared and will be held safely isolated and inside of a boundary provided by the AppDomain.

Load some new assemblies..
Suppose you want to load an updated dll into the application folder or subdirectory, the ASP.NET runtime will recognize it and and will start a new AppDomain because it cannot insert it to the running AppDomain, the result is that running requests will finish its work and after it they will work against the new AppDomain that holds the new dll and executing code.

Last word...
I think that one of the good adventages of the AppDomain is that you can allocate the wanted memory for your application (under its AppDomain) as much as you want (bounded by the process capability of course) and if there is a runtime crash, the rest of the applciations that runs over the current process will not crash.

I will glad to hear some comments and additions... :)

Posted by: Eran Nachum (c)
Post Date: 11/23/2006 3:03:00 PM (Jerusalem Standard Time, UTC+02:00)
Disclaimer | | Trackback   #
 Wednesday, August 02, 2006

Hello!

I am still working on a big web application in work. I will glad to tell you about the application, but this is for other conversation. I am glad to say that we are close to the end of the project and doing now last fine tuning on it.

The thing that I had to deal with for the last days is all the issue with publishing application errors in orderly fashion to the event viewer. The reason of doing it is to get the ability of tracking in runtime, bugs, errors or exceptions that can be appear while the application is in production. In this case we don't have the CLR debugger to find what was wrong (if something happend of course...), so we must publish the exception to the system's event viewer or just  to a simple Log file (which less recommended then publishing to the system's event viewer).

Now, to the implementation (the imporatnt thing!!!)

In order to publish error to the event viewer, we need to use the Microsoft.ApplicationBlocks.ExceptionManagement assembly of Microsoft. This assembly expose us all the publishing tools that we will need to publish an errors (and more...).

In my web application, in global.asax file, in Application_Error method, I wanted to publish the exception to the event viewer. It is very important to do it there, because in every application error, like runtime errors, exceptions and actions that the application and systme doesn't know to deal with, this method is being called (by the application of course).

Now, before publishing the error to the event viewer, you need to distinguish between the different exceptions. Do it with your own information about every exception that is happening but, it is important to know that also in every response's redirect (Response.Redirect (" ... ", true) or server's transfer (Server.Transfer (" ... ", true) an ThreadAbortException is being raised.

Exception lastError = Server.GetLastError();

if (Server.GetLastError() is ThreadAbortException || lastError.InnerException is ThreadAbortException)
{
   // Eat the exception - caused by Response.Redirect(..., true) or Server.Transfer(..., true).
   Microsoft.ApplicationBlocks.ExceptionManagement.ExceptionManager.Publish(lastError.GetBaseException());
   Server.ClearError();
}
else
{
   Microsoft.ApplicationBlocks.ExceptionManagement.ExceptionManager.Publish(lastError.GetBaseException());
   Server.ClearError();
   Server.Transfer("~/Error.aspx", false);
}

By this example you can see the publish exceptions handling.

Now, do not forget to declare in the web.config file the appliation name and the exceptions pulishing handling:

<exceptionManagement mode="on">
        <publisher assembly="Microsoft.ApplicationBlocks.ExceptionManagement" type="Microsoft.ApplicationBlocks.ExceptionManagement.DefaultPublisher" applicationname="APPLICATION_NAME"/>
</exceptionManagement>

One more thing... you need to register this assembly with the appliation name in the registry in purpose to let the application all the rights to publish the error in the event viewer, if you won't do it, the system won't let you write to the event viewer and you will get the exception: The event source ExceptionManagerInternalException does not exist and cannot be created with the current permissions. security exception and you will spend planty of time trying to solve it :) (like me...)

How to register this to the registry you ask?

Open notepad and write there this code:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\APPLICATION_NAME]
"EventMessageFile"="C:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727\\EventLogMessages.dll"

Save this file with .reg extension and double click on it, this will register this to the system's registry.

So, bye for now...

Posted by: Eran Nachum (c)
Post Date: 8/2/2006 7:47:28 AM (Jerusalem Standard Time, UTC+02:00)
Disclaimer | | Trackback   #