Microsoft has taken all of the right steps forward with the .NET Framework. DCOM is gone, and so are all of the inherent headaches that went with it. You no longer need to use COM+ to create scalable applications, although you can certainly use it if needed for the situation. Security is a lot easier to implement and a lot more robust in the .NET Framework—especially when working in an enterprise. There are several ways to go about building an enterprise application with .NET, including with ASP.NET, with Windows Forms, and with Web services. You will briefly look at the different techniques to create an enterprise application in the following sections.
With all the talk of the Internet simplifying everyone's life, it is natural that ASP.NET and Web forms are getting a lot of press. In my opinion, they get too much press, but I talk about that further on (see the "Using Windows Forms with a Distinctly .NET Twist" section). Prior to ASP.NET, I did not care for building Web applications because of the lack of power of the interface and the need to use a scripting language to control all of the programmatic access to the interface, but Microsoft hit a home run with this implementation. ASP.NET takes all the best parts of Visual Basic (or C# or whatever other .NET language you choose to use) and all the best parts of ASP, and combines them to make a rock-solid, easy-to-use, powerful Web development platform.
Because a Web interface is still fairly limited, all of the power of the regular .NET Framework controls are not available to the Web versions. For example, you can fill the listbox control in the Windows.Forms namespace just by adding objects, but you must use the standard string entry for the listbox provided by the Web.UI namespace. There are many differences such as these that take a little getting used to but are beyond the scope of this book to cover in detail.
In the enterprise, this type of implementation has many advantages. The first advantage is that you can update the application without having to redistribute it to the users. In many corporate environments, the users do not have permission to install applications on their machines. In these cases, an additional mechanism is needed to perform the installation. In many cases it requires a group administrator to go around to all the machines, log on, and perform the installation. This is not only expensive, but it is time consuming. While one group of users has the new application, another group is still using the old application. This makes upgrades extremely difficult. Another advantage to using ASP.NET is that the application does not need to be installed on the user's machine at all! An additional advantage is security. Using Internet Information Server (IIS), you can authenticate users when they first go to an ASP.NET Web site using one of several forms of authentication (discussed in more detail in Chapter 2, "Building an N-Tier Application"). It provides a double layer of protection—on the Web site and at the database level.
Web forms, however, usually lead to a two-tier architecture, not a three-tier architecture. Most of the applications I have seen that are Web forms based contain much of the logic in the .aspx.vb file (which is the code behind the form module). This means the business logic is tightly coupled with the presentation layer. You must remove the logic from the code-behind page and move it into separate classes and a separate assembly if you desire to decouple these layers.
This method is classic because of the large shift in development to Web interfaces and because many people believe that Windows applications will no longer be used as enterprises gradually make the shift to Internet and intranet-based technologies. This is far from the truth, however, especially with the advent of .NET, as I explain in the next section. Windows forms are standard windows built into an application that needs to be installed onto the user's machine. With .NET, the installation can be as simple as copying files onto the user's machine, or it can be more involved and actually need a setup program to be run. If the application only needs to be installed using XCOPY, it helps mitigate some of the expense of upgrading the application. You can simply place the new files on a server and instruct the user to download them to the local machine in the correct directory. If the application requires an installation, the drawbacks mentioned in the previous section apply here.
There is also one other difficulty in this type of application. The users need to have the .NET Framework installed on their machines. Although the .NET Framework redistributable file is fairly small (only 20MB), it still requires someone logged on with the privileges to install an application. And if the users have this privilege, then there is still the matter of the users having to go out and get the package to install. Alternatively, you can include this package in a setup program—although this only has to occur once, it does need to occur.
The .NET Framework is really a marvel of programming. It is the best thing to hit the programming world since Visual Basic first hit the market. The power of an application to be able to read information about itself during runtime is incredible. In .NET parlance, this is called reflection.
Reflection has been available in Java since its inception. However, .NET takes reflection and builds on it to make it more powerful through the introduction of custom attributes. Chapter 10, "Using Reflection," covers this in more detail.
You can deploy Windows forms, with reflection, using a method called auto-deployment, which can be an effective alternative to the downsides of Web application development. So, what exactly is auto-deployment, and why do I suggest it? Auto-deployment uses what is known as a stub architecture. That is, one small executable file is copied to the user's machine. This stub has almost no functionality and is very small (I suggest using a splash screen, which typically turns out to be a whopping 15KB in size). The only function it has is to load the main part of the application from an IIS server. As long as the assemblies are not too large, the amount of time necessary to download the actual application is fairly short. The application downloads in a trickle fashion. Let's say, for example, that the application is 10MB and the presentation part of the application is about 7MB. The presentation part is broken up into 14 assemblies that are only 500KB in size. The splash screen would load up the first form, which would presumably be the main form, and all of the other forms contained within that assembly. The application would not start downloading 7MB worth of data; it would only download 500KB of data. Even over a dial-up connection (yes, people still have those), this is not such a large delay.
The great news about using this technique is that the download only needs to occur once. The next time the user runs the application, the first thing that it will do is check the version number (this is where reflection comes in) of the assembly located on the local machine against the version number of the assembly on the remote machine. If they are the same, the application uses the locally cached version. Otherwise, it downloads the updated version. But the great trick about all of this is that the code to achieve this lives only in the stub. The rest of the forms can instantiate other forms in the normal manner. The reason for this is that the assembly knows to go back and look in the same place as it was originally loaded from for the next piece of code. This makes development of this type of application incredibly easy because you can develop the application entirely on your machine and then at the last minute convert to the stub architecture by the addition of the stub. That's all there is to it.
There is one issue with this type of stub deployment at the time of this writing. Through tests I conducted for a project, I found a bug with this type of deployment. It works great for a two-tier application but not for a three-tier application. The error occurs because the needed assemblies are being searched for in the wrong directories. Microsoft has confirmed this is a bug and is in the process of correcting it.
It makes installation of the application easy because you can place a link to an EXE file on a Web page and the user can save it to their machine and run it.
Although this does present the problem of needing to have .NET on the local machine, it makes updates very cheap and easy. No one has to stop using the application; they will just get the new version next time they log on.
The .NET Framework, in conjunction with IIS, uses what is called a shadow copy mechanism. That is when the actual component that is deployed is not the component that is accessed. The component that is accessed is actually an in-memory representation of the component. Therefore, if an application needs to be updated, the new components can just be copied on top of the old, and the next time a call to the components are made, the new versions will be used. When the last connection to the old version is released, that version will be removed from memory and the new version will be used.
In the future this may be a preferred method of application development, but it still requires the .NET Framework on the local machine. I hope in the future Microsoft will create a mechanism like the one used by Java to prompt the user to download the .NET Framework the first time they try to run an application such as this, but that may be a long way off.
Everyone has been jumping on the Web services bandwagon lately. I have seen so much press and heard so many people give their opinion of this "new" technology that it has just become too much. What are Web services? Well, it turns out that Web services are just Remote Procedure Calls (RPCs). This is not new technology. It has been around for a long time. So what makes Web services special then? Well, that is the real trick—being different from the crowd. And .NET's Web services are special indeed. What makes this implementation of a RPC different is that the data is sent as a self-describing Simple Object Access Protocol (SOAP) message. This means that it is not only platform independent but that you cannot embed viruses in a call to a Web service (nor can you return a virus from a call to a Web service).
In terms of .NET, creating a Web service is simplicity itself. You stick the <WebMethod()> tag in front of a function (or subroutine, but you will not see that often because probably you are trying to get some data from the service). That is all there is to it. .NET takes care of the rest for you. It takes care of deserializing the SOAP request that is sent to it and serializing the data into the SOAP format for return to the caller. It works absolutely transparently. And you can call Web services from Visual Basic 6 and other languages as long as they can parse a SOAP string. Java also has Web services, but its implementation is new and not a core part of the language (as of this writing); in other words, it is an add-on at this point.
A key part of consuming Web services involves being able to find available Web services. You locate these services by searching a Universal Description, Discovery, and Integration (UDDI) directory. Currently there are two major public UDDIs, put out by Microsoft and IBM. (These are actually just one UDDI that is replicated between Microsoft and IBM.) For a business to be able to use and consume its own Web services, the business must eventually set up its own UDDI directory. You will learn about setting up an enterprise UDDI and making it usable by the enterprise in Chapter 11, "Web Services and the UDDI." Later on in the book you will also create your own Web service, and you will learn how to register the Web service with a UDDI. Microsoft and IBM also maintain test UDDI directories for people to practice registering and searching for Web services.
There are several ways in which .NET can scale an application, but there is one easy way to do this: IIS. If the components are hosted in IIS, then it is a simple matter of moving them from a single box to a Web farm. A Web farm is just a group of IIS servers that have traffic sent to them by a load balancing router. Microsoft also provides a server called Application Center Server, which is designed to act as a load balancing server in place of a router designed for this purpose. As a developer there is only one thing you need to plan for to achieve this scalability: Your components must be stateless. Stateless components are those that do not maintain any information between calls. Assume that you have an object called objPerson that contains information about a person. The following lines of code indicate an object that is stateful, or maintains state between calls:
objPerson.FirstName = John objPerson.LastName = Smith objPerson.Save
As you can see, three calls are made on the person object, and it can be assumed that when you call the Save method of the person object, you are saving the first and last name of the person. The next example shows a stateless object:
Public Structure structperson Public FirstName as string Public LastName as string End Structure Private Sub Save() Dim sPerson as structPerson Dim objPerson as Person sPerson.FirstName = John sPerson.LastName = Smith objPerson = new Person objPerson.Save(sPerson) objPerson = nothing End Sub
As you can see in this example, there is only one call made on the person object, and it is passed all of the data it needs in the one call. After the call is made, the information will either be saved or it will not be saved, but the object will not maintain that information. It does not need to because the calling code maintains the necessary information.
The difference between the first example and the second example is important. There are two different types of calls that you can make to remote objects: SingleCall and Singleton. SingleCall is when a new object is created for every call made to the remote object by a different client. Singleton is when one object is created on the server and every connection to the server uses this one instance of the object. In terms of scalability, if you are using the SingleCall method and 500,000 users hit the server at the same time, 500,000 copies of your object will be created. You would find yourself quickly running out of memory! Using the Singleton method, you can have as many connections as you want, but only one object is ever created. The key to this is that the objects must be stateless, as in the second example; otherwise the different processes would interfere with each other.