| ASP.NET Performance |
| To build ASP.NET applications that meet your performance objectives, you need to understand the places where bottlenecks typically occur, the causes of the bottlenecks, and the steps to take to prevent the bottlenecks from occurring in your application. A combination of sound architecture and design, best practice coding techniques, and optimized platform and Microsoft® .NET Framework configuration is required. This article addresses each of these areas. |
| The Contents in this section provide guidance on how to improve the security of your application through user authentication, authorization, data encryption, and more. |
| Please fill up the form below and we will submit a proposal for your project. Alternatively, you can send
email to contact@optionm.net with the project
requirements. |
|
|
|
|
|
 |
| Architecture |
|
|
| ASP.NET requires a host. On Windows Server 2003, the default host is the Internet Information Services (IIS) 6.0 worker process (W3wp.exe). When you use the ASP.NET Process Model, the host is the ASP.NET worker process (Aspnet_wp.exe). |
|
| When a request is received by ASP.NET, the request is handled by the HttpRuntime object. The HttpRuntime is responsible for application creation and initialization, managing the request queue and thread pool, and dispatching the incoming requests to the correct application. After the request is dispatched to the appropriate application, the request is passed through a pipeline. This pipeline is a staged, event-based execution framework consisting of multiple HttpModule objects and a single HttpHandler object. This architecture is shown in Figure below |
|
 |
|
| Figure showing ASP.NET runtime infrastructure |
| HttpModule objects participate in the pipeline by handling predefined events that ASP.NET exposes. These events include BeginRequest, AuthenticateRequest, and EndRequest. The request flows through the pipeline of HttpModule objects and is then run by a single HttpHandler. After the event handler is completed, the request then flows back through the pipeline and is sent to the client. |
|
| Throughout the entire lifetime of a request, a context is exposed. The HttpContext object encapsulates information about individual requests and their associated responses. |
|
|
|
| Click here to submit your project requirements to Option Matrix, India. |
| Back to top |
 |
| Performance and Scalability Issues |
|
|
| The main issues that can adversely affect the performance and scalability of your ASP.NET application are summarized below. Subsequent sections in this article provide strategies and technical information to prevent or resolve each of these issues. |
|
| Resource affinity. Resource affinity can prevent you from adding more servers, or resource affinity can reduce the benefits of adding more CPUs and memory. Resource affinity occurs when code needs a specific thread, CPU, component instance, or server. |
| Excessive allocations. Applications that allocate memory excessively on a per-request basis consume memory and create additional work for garbage collection. The additional garbage collection work increases CPU utilization. These excessive allocations may be caused by temporary allocations. For example, the excessive allocations may be caused by excessive string concatenation that uses the += operator in a tight loop. |
| Failure to share expensive resources. Failing to call the Dispose or Close method to release expensive resources, such as database connections, may lead to resource shortages. Closing or disposing resources permits the resources to be reused more efficiently. |
| Blocking operations. The single thread that handles an ASP.NET request is blocked from servicing additional user requests while the thread is waiting for a downstream call to return. Calls to long-running stored procedures and remote objects may block a thread for a significant amount of time. |
| Misusing threads. Creating threads for each request incurs thread initialization costs that can be avoided. Also, using single-threaded apartment (STA) COM objects incorrectly may cause multiple requests to queue up. Multiple requests in the queue slow performance and create scalability issues. |
| Making late-bound calls. Late-bound calls require extra instructions at runtime to identify and load the code to be run. Whether the target code is managed or unmanaged, you should avoid these extra instructions. |
| Misusing COM interop. COM interop is generally very efficient, although many factors affect its performance. These factors include the size and type of the parameters that you pass across the managed/unmanaged boundary and crossing apartment boundaries. Crossing apartment boundaries may require expensive thread switches. |
| Large pages. Page size is affected by the number and the types of controls on the page. Page size is also affected by the data and images that you use to render the page. The more data you send over the network, the more bandwidth you consume. When you consume high levels of bandwidth, you are more likely to create a bottleneck. |
| Failure to use data caching appropriately. Failure to cache static data, caching too much data so that the items get flushed out, caching user data instead of application-wide data, and caching infrequently used items may limit your system's performance and scalability. |
| Failure to use output caching appropriately. If you do not use output caching or if you use it incorrectly, you can add avoidable strain to your Web server. |
| Inefficient rendering. Interspersing HTML and server code, performing unnecessary initialization code on page postback, and late-bound data binding may all cause significant rendering overhead. This may decrease the perceived and true page performance. |
|
|
|
|
| Click here to submit your project requirements to Option Matrix, India. |
| Back to top |
 |
| Design Considerations |
|
|
| Building high-performance ASP.NET applications is significantly easier if you design with performance in mind. Make sure you develop a performance plan from the outset of your project. Never try to add performance as a post-build step. Also, use an iterative development process that incorporates constant measuring between iterations. |
|
| By following best practice design guidelines, you significantly increase your chances of creating a high-performance Web application. Consider the following design guidelines: |
|
| Consider security and performance. |
| Partition your application logically. |
| Evaluate affinity. |
| Reduce round trips. |
| Avoid blocking on long-running tasks. |
| Use caching. |
| Avoid unnecessary exceptions. |
|
|
|
|
| Click here to submit your project requirements to Option Matrix, India. |
| Back to top |
 |
| Consider Security and Performance |
|
|
| Your choice of authentication scheme can affect the performance and scalability of your application. You need to consider the following issues: |
|
| Identities. Consider the identities you are using and the way that you flow identity through your application. To access downstream resources, you can use the ASP.NET process identity or another specific service identity. Or, you can enable impersonation and flow the identity of the original caller. If you connect to Microsoft SQL ServerT, you can also use SQL authentication. However, SQL authentication requires you to store credentials in the database connection string. Storing credentials in the database connection string is not recommended from a security perspective. When you connect to a shared resource, such as a database, by using a single identity, you benefit from connection pooling. Connection pooling significantly increases scalability. If you flow the identity of the original caller by using impersonation, you cannot benefit from efficient connection pooling, and you have to configure access control for multiple individual user accounts. For these reasons, it is best to use a single trusted identity to connect to downstream databases. |
| Managing credentials. Consider the way that you manage credentials. You have to decide if your application stores and verifies credentials in a database, or if you want to use an authentication mechanism provided by the operating system where credentials are stored for you in the Active Directory® directory service. |
| You should also determine the number of concurrent users that your application can support and determine the number of users that your credential store (database or Active Directory) can handle. You should perform capacity planning for your application to determine if the system can handle the anticipated load. |
| Protecting credentials. Your decision to encrypt and decrypt credentials when they are sent over the network costs additional processing cycles. If you use authentication schemes such as Windows® Forms authentication or SQL authentication, credentials flow in clear text and can be accessed by network eavesdroppers. In these cases, how important is it for you to protect them as they are passed across the network? Decide if you can choose authentication schemes that are provided by the operating system, such as NTLM or the Kerberos protocol, where credentials are not sent over the network to avoid encryption overhead. |
| Cryptography. If your application only needs to ensure that information is not tampered with during transit, you can use keyed hashing. Encryption is not required in this case, and it is relatively expensive compared to hashing. If you need to hide the data that you send over the network, you require encryption and probably keyed hashing to ensure data validity. When both parties can share the keys, using symmetric encryption provides improved performance in comparison to asymmetric encryption. Although larger key sizes provide greater encryption strength, performance is slower relative to smaller key sizes. You must consider this type of performance and balance the larger key sizes against security tradeoffs at design time. |
|
|
|
|
| Click here to submit your project requirements to Option Matrix, India. |
| Back to top |
 |
| Tips for Writing High-Performance Web Applications |
|
|
| There are two types of performance improvements described in this section: large optimizations, such as using the ASP.NET Cache, and tiny optimizations that repeat themselves. These tiny optimizations are sometimes the most interesting. You make a small change to code that gets called thousands and thousands of times. With a big optimization, you might see overall performance take a large jump. With that general information established, let's look at ten tips that can help your application perform better. I'll begin with the changes that can make the biggest difference. |
|
| Tip 1-Return Multiple Resultsets |
|
| Review your database code to see if you have request paths that go to the database more than once. Each of those round-trips decreases the number of requests per second your application can serve. By returning multiple resultsets in a single database request, you can cut the total time spent communicating with the database. You'll be making your system more scalable, too, as you'll cut down on the work the database server is doing managing requests. |
|
| While you can return multiple resultsets using dynamic SQL, I prefer to use stored procedures. It's arguable whether business logic should reside in a stored procedure, but I think that if logic in a stored procedure can constrain the data returned (reduce the size of the dataset, time spent on the network, and not having to filter the data in the logic tier), it's a good thing. |
|
| Using a SqlCommand instance and its ExecuteReader method to populate strongly typed business classes, you can move the resultset pointer forward by calling NextResult. Figure 1 shows a sample conversation populating several ArrayLists with typed classes. Returning only the data you need from the database will additionally decrease memory allocations on your server. |
|
 |
Figure 1 Extracting Multiple Resultsets from a DataReader |
|
|
 |
Copy Code |
|
// read the first resultset
reader = command.ExecuteReader();
// read the data from that resultset
while (reader.Read()) {
suppliers.Add(PopulateSupplierFromIDataReader( reader ));
}
// read the next resultset
reader.NextResult();
// read the data from that second resultset
while (reader.Read()) {
products.Add(PopulateProductFromIDataReader( reader ));
} |
|
|
| Tip 2-Paged Data Access |
| The ASP.NET DataGrid exposes a wonderful capability: data paging support. When paging is enabled in the DataGrid, a fixed number of records is shown at a time. Additionally, paging UI is also shown at the bottom of the DataGrid for navigating through the records. The paging UI allows you to navigate backwards and forwards through displayed data, displaying a fixed number of records at a time. |
|
| There's one slight wrinkle. Paging with the DataGrid requires all of the data to be bound to the grid. For example, your data layer will need to return all of the data and then the DataGrid will filter all the displayed records based on the current page. If 100,000 records are returned when you're paging through the DataGrid, 99,975 records would be discarded on each request (assuming a page size of 25). As the number of records grows, the performance of the application will suffer as more and more data must be sent on each request. |
|
| One good approach to writing better paging code is to use stored procedures. |
| In Community Server, we wrote a paging server control to do all the data paging. You'll see that I am using the ideas discussed in Tip 1, returning two resultsets from one stored procedure: the total number of records and the requested data. |
|
| The total number of records returned can vary depending on the query being executed. For example, a WHERE clause can be used to constrain the data returned. The total number of records to be returned must be known in order to calculate the total pages to be displayed in the paging UI. For example, if there are 1,000,000 total records and a WHERE clause is used that filters this to 1,000 records, the paging logic needs to be aware of the total number of records to properly render the paging UI. |
|
| Tip 3-Connection Pooling |
| Setting up the TCP connection between your Web application and SQL ServerT can be an expensive operation. Developers at Microsoft have been able to take advantage of connection pooling for some time now, allowing them to reuse connections to the database. Rather than setting up a new TCP connection on each request, a new connection is set up only when one is not available in the connection pool. When the connection is closed, it is returned to the pool where it remains connected to the database, as opposed to completely tearing down that TCP connection. |
|
| Of course you need to watch out for leaking connections. Always close your connections when you're finished with them. I repeat: no matter what anyone says about garbage collection within the Microsoft® .NET Framework, always call Close or Dispose explicitly on your connection when you are finished with it. Do not trust the common language runtime (CLR) to clean up and close your connection for you at a predetermined time. The CLR will eventually destroy the class and force the connection closed, but you have no guarantee when the garbage collection on the object will actually happen. |
|
| To use connection pooling optimally, there are a couple of rules to live by. First, open the connection, do the work, and then close the connection. It's okay to open and close the connection multiple times on each request if you have to (optimally you apply Tip 1) rather than keeping the connection open and passing it around through different methods. Second, use the same connection string (and the same thread identity if you're using integrated authentication). If you don't use the same connection string, for example customizing the connection string based on the logged-in user, you won't get the same optimization value provided by connection pooling. And if you use integrated authentication while impersonating a large set of users, your pooling will also be much less effective. The .NET CLR data performance counters can be very useful when attempting to track down any performance issues that are related to connection pooling. |
|
| Whenever your application is connecting to a resource, such as a database, running in another process, you should optimize by focusing on the time spent connecting to the resource, the time spent sending or retrieving data, and the number of round-trips. Optimizing any kind of process hop in your application is the first place to start to achieve better performance. |
|
| The application tier contains the logic that connects to your data layer and transforms data into meaningful class instances and business processes. For example, in Community Server, this is where you populate a Forums or Threads collection, and apply business rules such as permissions; most importantly it is where the Caching logic is performed. |
|
| Tip 4-ASP.NET Cache API |
| One of the very first things you should do before writing a line of application code is architect the application tier to maximize and exploit the ASP.NET Cache feature. |
|
| If your components are running within an ASP.NET application, you simply need to include a reference to System.Web.dll in your application project. When you need access to the Cache, use the HttpRuntime.Cache property (the same object is also accessible through Page.Cache and HttpContext.Cache). |
|
| There are several rules for caching data. First, if data can be used more than once it's a good candidate for caching. Second, if data is general rather than specific to a given request or user, it's a great candidate for the cache. If the data is user- or request-specific, but is long lived, it can still be cached, but may not be used as frequently. Third, an often overlooked rule is that sometimes you can cache too much. Generally on an x86 machine, you want to run a process with no higher than 800MB of private bytes in order to reduce the chance of an out-of-memory error. Therefore, caching should be bounded. In other words, you may be able to reuse a result of a computation, but if that computation takes 10 parameters, you might attempt to cache on 10 permutations, which will likely get you into trouble. One of the most common support calls for ASP.NET is out-of-memory errors caused by overcaching, especially of large datasets.Common Performance Myths |
|
| One of the most common myths is that C# code is faster than Visual Basic code. There is a grain of truth in this, as it is possible to take several performance-hindering actions in Visual Basic that are not possible to accomplish in C#, such as not explicitly declaring types. But if good programming practices are followed, there is no reason why Visual Basic and C# code cannot execute with nearly identical performance. To put it more succinctly, similar code produces similar results. |
|
| Another myth is that codebehind is faster than inline, which is absolutely false. It doesn't matter where your code for your ASP.NET application lives, whether in a codebehind file or inline with the ASP.NET page. Sometimes I prefer to use inline code as changes don't incur the same update costs as codebehind. For example, with codebehind you have to update the entire codebehind DLL, which can be a scary proposition. |
|
| Myth number three is that components are faster than pages. This was true in Classic ASP when compiled COM servers were much faster than VBScript. With ASP.NET, however, both pages and components are classes. Whether your code is inline in a page, within a codebehind, or in a separate component makes little performance difference. Organizationally, it is better to group functionality logically this way, but again it makes no difference with regard to performance. |
|
| The final myth I want to dispel is that every functionality that you want to occur between two apps should be implemented as a Web service. Web services should be used to connect disparate systems or to provide remote access to system functionality or behaviors. They should not be used internally to connect two similar systems. While easy to use, there are much better alternatives. The worst thing you can do is use Web services for communicating between ASP and ASP.NET applications running on the same server, which I've witnessed all too frequently. |
|
 |
|
| Figure Above ASP.NET Cache |
|
| There are a several great features of the Cache that you need to know. The first is that the Cache implements a least-recently-used algorithm, allowing ASP.NET to force a Cache purge-automatically removing unused items from the Cache-if memory is running low. Secondly, the Cache supports expiration dependencies that can force invalidation. These include time, key, and file. Time is often used, but with ASP.NET 2.0 a new and more powerful invalidation type is being introduced: database cache invalidation. This refers to the automatic removal of entries in the cache when data in the database changes. For more information on database cache invalidation, see Dino Esposito's Cutting Edge column in the July 2004 issue of MSDN®Magazine. For a look at the architecture of the cache, see Figure above |
|
| Tip 5-Per-Request Caching |
| Earlier in the article, I mentioned that small improvements to frequently traversed code paths can lead to big, overall performance gains. One of my absolute favorites of these is something I've termed per-request caching. |
|
| Whereas the Cache API is designed to cache data for a long period or until some condition is met, per-request caching simply means caching the data for the duration of the request. A particular code path is accessed frequently on each request but the data only needs to be fetched, applied, modified, or updated once. This sounds fairly theoretical, so let's consider a concrete example. |
|
| In the Forums application of Community Server, each server control used on a page requires personalization data to determine which skin to use, the style sheet to use, as well as other personalization data. Some of this data can be cached for a long period of time, but some data, such as the skin to use for the controls, is fetched once on each request and reused multiple times during the execution of the request. |
|
| To accomplish per-request caching, use the ASP.NET HttpContext. An instance of HttpContext is created with every request and is accessible anywhere during that request from the HttpContext.Current property. The HttpContext class has a special Items collection property; objects and data added to this Items collection are cached only for the duration of the request. Just as you can use the Cache to store frequently accessed data, you can use HttpContext.Items to store data that you'll use only on a per-request basis. The logic behind this is simple: data is added to the HttpContext.Items collection when it doesn't exist, and on subsequent lookups the data found in HttpContext.Items is simply returned. |
|
| Tip 6-Background Processing |
| The path through your code should be as fast as possible, right? There may be times when you find yourself performing expensive tasks on each request or once every n requests. Sending out e-mails or parsing and validation of incoming data are just a few examples. |
|
| When tearing apart ASP.NET Forums 1.0 and rebuilding what became Community Server, we found that the code path for adding a new post was pretty slow. Each time a post was added, the application first needed to ensure that there were no duplicate posts, then it had to parse the post using a "badword" filter, parse the post for emoticons, tokenize and index the post, add the post to the moderation queue when required, validate attachments, and finally, once posted, send e-mail notifications out to any subscribers. Clearly, that's a lot of work. |
|
| It turns out that most of the time was spent in the indexing logic and sending e-mails. Indexing a post was a time-consuming operation, and it turned out that the built-in System.Web.Mail functionality would connect to an SMTP server and send the e-mails serially. As the number of subscribers to a particular post or topic area increased, it would take longer and longer to perform the AddPost function. |
|
| Indexing e-mail didn't need to happen on each request. Ideally, we wanted to batch this work together and index 25 posts at a time or send all the e-mails every five minutes. We decided to use the same code I had used to prototype database cache invalidation for what eventually got baked into Visual Studio® 2005. |
|
| The Timer class, found in the System.Threading namespace, is a wonderfully useful, but less well-known class in the .NET Framework, at least for Web developers. Once created, the Timer will invoke the specified callback on a thread from the ThreadPool at a configurable interval. This means you can set up code to execute without an incoming request to your ASP.NET application, an ideal situation for background processing. You can do work such as indexing or sending e-mail in this background process too. |
|
| There are a couple of problems with this technique, though. If your application domain unloads, the timer instance will stop firing its events. In addition, since the CLR has a hard gate on the number of threads per process, you can get into a situation on a heavily loaded server where timers may not have threads to complete on and can be somewhat delayed. ASP.NET tries to minimize the chances of this happening by reserving a certain number of free threads in the process and only using a portion of the total threads for request processing. However, if you have lots of asynchronous work, this can be an issue. |
|
| Tip 7-Page Output Caching and Proxy Servers |
| ASP.NET is your presentation layer (or should be); it consists of pages, user controls, server controls (HttpHandlers and HttpModules), and the content that they generate. If you have an ASP.NET page that generates output, whether HTML, XML, images, or any other data, and you run this code on each request and it generates the same output, you have a great candidate for page output caching. |
|
| By simply adding this line to the top of your page you can effectively generate the |
 |
Copy Code |
|
| <%@ Page OutputCache VaryByParams="none" Duration="60" %> |
|
|
| output for this page once and reuse it multiple times for up to 60 seconds, at which point the page will re-execute and the output will once be again added to the ASP.NET Cache. This behavior can also be accomplished using some lower-level programmatic APIs, too. There are several configurable settings for output caching, such as the VaryByParams attribute just described. VaryByParams just happens to be required, but allows you to specify the HTTP GET or HTTP POST parameters to vary the cache entries. For example, default.aspx?Report=1 or default.aspx?Report=2 could be output-cached by simply setting VaryByParam="Report". Additional parameters can be named by specifying a semicolon-separated list. |
|
| Many people don't realize that when the Output Cache is used, the ASP.NET page also generates a set of HTTP headers that downstream caching servers, such as those used by the Microsoft Internet Security and Acceleration Server or by Akamai. When HTTP Cache headers are set, the documents can be cached on these network resources, and client requests can be satisfied without having to go back to the origin server.
Using page output caching, then, does not make your application more efficient, but it can potentially reduce the load on your server as downstream caching technology caches documents. Of course, this can only be anonymous content; once it's downstream, you won't see the requests anymore and can't perform authentication to prevent access to it. |
|
| Tip 8-Run IIS 6.0 (If Only for Kernel Caching) |
| If you're not running IIS 6.0 (Windows ServerT 2003), you're missing out on some great performance enhancements in the Microsoft Web server. In Tip 7, I talked about output caching. In IIS 5.0, a request comes through IIS and then to ASP.NET. When caching is involved, an HttpModule in ASP.NET receives the request, and returns the contents from the Cache. |
|
| If you're using IIS 6.0, there is a nice little feature called kernel caching that doesn't require any code changes to ASP.NET. When a request is output-cached by ASP.NET, the IIS kernel cache receives a copy of the cached data. When a request comes from the network driver, a kernel-level driver (no context switch to user mode) receives the request, and if cached, flushes the cached data to the response, and completes execution. This means that when you use kernel-mode caching with IIS and ASP.NET output caching, you'll see unbelievable performance results. At one point during the Visual Studio 2005 development of ASP.NET, I was the program manager responsible for ASP.NET performance. The developers did the magic, but I saw all the reports on a daily basis. The kernel mode caching results were always the most interesting. The common characteristic was network saturation by requests/responses and IIS running at about five percent CPU utilization. It was amazing! There are certainly other reasons for using IIS 6.0, but kernel mode caching is an obvious one. |
|
| Tip 9-Use Gzip Compression |
| While not necessarily a server performance tip (since you might see CPU utilization go up), using gzip compression can decrease the number of bytes sent by your server. This gives the perception of faster pages and also cuts down on bandwidth usage. Depending on the data sent, how well it can be compressed, and whether the client browsers support it (IIS will only send gzip compressed content to clients that support gzip compression, such as Internet Explorer 6.0 and Firefox), your server can serve more requests per second. In fact, just about any time you can decrease the amount of data returned, you will increase requests per second. |
|
| The good news is that gzip compression is built into IIS 6.0 and is much better than the gzip compression used in IIS 5.0. Unfortunately, when attempting to turn on gzip compression in IIS 6.0, you may not be able to locate the setting on the properties dialog in IIS. The IIS team built awesome gzip capabilities into the server, but neglected to include an administrative UI for enabling it. To enable gzip compression, you have to spelunk into the innards of the XML configuration settings of IIS 6.0 (which isn't for the faint of heart). |
|
| Tip 10-Server Control View State |
| View state is a fancy name for ASP.NET storing some state data in a hidden input field inside the generated page. When the page is posted back to the server, the server can parse, validate, and apply this view state data back to the page's tree of controls. View state is a very powerful capability since it allows state to be persisted with the client and it requires no cookies or server memory to save this state. Many ASP.NET server controls use view state to persist settings made during interactions with elements on the page, for example, saving the current page that is being displayed when paging through data. |
|
| There are a number of drawbacks to the use of view state, however. First of all, it increases the total payload of the page both when served and when requested. There is also an additional overhead incurred when serializing or deserializing view state data that is posted back to the server. Lastly, view state increases the memory allocations on the server. |
|
| Several server controls, the most well known of which is the DataGrid, tend to make excessive use of view state, even in cases where it is not needed. The default behavior of the ViewState property is enabled, but if you don't need it, you can turn it off at the control or page level. Within a control, you simply set the EnableViewState property to false, or you can set it globally within the page using this setting: |
|
 |
Copy Code |
|
| <%@ Page EnableViewState="false" %> |
|
|
| If you are not doing postbacks in a page or are always regenerating the controls on a page on each request, you should disable view state at the page level. |
|
| Conclusion |
| These are some tips that are useful for writing high-performance ASP.NET applications. As mentioned at the beginning of this article, this is more a preliminary guide than the last word on ASP.NET performance. |
|
|
|
| Click here to submit your project requirements to Option Matrix, India. |
| Back to top |
|
| Option Matrix Featured Case Studies |
|
| Option Matrix Whitepapers |
|
|
|
|
| Portal for Multi-location Hospital |
| The client was a healthcare provider (multi-location hospital) for the local resident patients having sleeping disorders. Option Matrix's scope of consulting was for their Seattle, |
|
|
|
| Health Fitness Portal |
| Client was establishing a Health Fitness Center at California established in June 2006 by a team of local Antelope Valley residents. It was offered full complement of new and innovative |
|
|
|
| Sleep Disorders Hospital Application |
| This project was the company service portal of "Client" for patients suffering from sleep disorders. It was information about the company, key personnel, HIPPA privacy, education resources, |
|
|
|
| Batteries Ecommerce Portal |
| The objective was to design an e-commerce website for Client to display their catalog of batteries online and collect orders which was forwarded by e-mail to be serviced by a third |
|
|
|
| Spices & Herbs Ecommerce Website |
| The overall purpose of this project was to develop an intuitive and professional spice and herbal ecommerce web site. This web site was accessed by site visitors, members (retail consumers), |
|
|
|
| Portal for Web Design Firm |
| The client, a web design firm located in USA. It positions itself as an idea company and offers services such as website design / development coupled with creative marketing, Internet |
|
|
|
| Dynamic Content Portal |
| The overall purpose of the project was to redesign a database driven dynamic version of the existing site including migration of existing content on the site to the new site design and |
|
|
|
| Networking Systems Ecommerce |
| The USA Based client was one of the leading provider of used and Refurbished Cisco Systems, Extreme Networks, Juniper and Foundry equipment. The client has the experience |
|
|
|
| 3rd Party Order Fulfillment |
| This project envisages provision of e-commerce for people in continent B countries who cannot do such transactions in normal course with US based online retailers as shipments |
|
|
|
| Multi-lingual Recruiting Portal |
| This project was for building a specialized job portal for Tourism Schools in Austria. This institutions offer training that enables college students or graduates to get trained for jobs in hotels, |
|
|
|
| Corporate Web Portal |
| The client was focused on providing process control solutions to the manufacturing and related industries. Established in 1989, this Client was a BSI-certified ISO 9001:2000 |
|
|
|
| Business Community Portal |
| The overall purpose of this project was to extend the features of existing business community web application meant for New Platform of projects for Team Formation and Expertise Management |
|
|
|
| Online Generic Store Portal |
| This project was intended to be a generic store front that was customized for several clients in the future. The intended objective was to build once and deploy for several clients with easy customization. |
|
|
|
| CMS Portal |
| The overall purpose of the project was to redesign a database driven dynamic version of the existing site including migration of existing content on the site to the new site design |
|
|
|
| HR Marketplace |
| This project has focused on development for Human Resources professionals who was seeking quality, unbiased information necessary to make educated buying decisions while keeping |
|
|
|
| Portal for IT Infrastructure Provider |
| An existing company of the client was looking for development of this project with redevelop the company profile and informational website and requires a graphic redesign along |
|
|
|
| Portal for Online Cosmetics Store |
| This project Development was focused on a pre-launch splash page that would capture email addresses to be used to communicate with consumer & Send confirmation email |
|
|
|
| Online Shipment Tracking |
| Development of this application was taken up to enable the customers to track the status of their shipments for a third party logistics provider and analyze all the information. |
|
|
|
| Online Survey Measurement Portal |
| Client had required a web application for a charitable association which provides funds to a set up 200 or more schools. Client administers survey to monitor the correct usage of funds |
|
|
|
| Performance Measurement Portal |
| The overall purpose of this system was to enable a company's document & its business strategy along with critical success factors and define an information bank with key |
|
|
|
| Case Studies A - Z Index |
| We have Provided a full history of our project Case Studies across all Technologies, Services and Industries. |
|
|
|
|
|
|
|
|
| Healthcare Introduction |
| Healthcare is something that everyone needs but not something that everyone has access to. It's quite true that in theory everyone is able to get some type of healthcare. |
| | | | | | | |