ASP.NET Application Optimization Tips

By Sudha Polapragada

Generally, large-scale Web applications will be deployed to load-balancing servers to share traffic evenly across a number of application servers. Additional application servers then can be added without making any changes to your application. For applications deployed to stand-alone servers, more hardware can be added to improve performance.

The application server or load-balanced servers might enhance Web application performance; however, there are ways to enhance performance on the developer side as well. By following certain optimization techniques while you are writing your application code, you can also reduce a lot of performance issues. It is essential to understand which parts of your code can be optimized, and how you can measure improvements in performance compared to a baseline.

Below, I share a number of optimization techniques that you can use:

  • Use the connection pooling so that the connections can be re-used when future requests to the database are required.
  • Dispose of objects properly from the caller method than in the called method.
  • Reduce page load times by techniques such as minimizing the scripts. Use script file references in pages to enable the client to cache these scripts for subsequent requests.
  • Remove white spaces and extra tags to dramatically reduce the size of your pages. Limit the use of graphics and consider using compressed graphics.
  • Consider using cascading style sheets to avoid sending the same formatting directives to the client repeatedly.
  • Control names should be short because they generate unique HTMLID names. If a control is used inside nested controls, a 10-character control name can easily turn into 30 to 40 characters.
  • Use Page.IsPostBack to minimize redundant processing.
  • Use for each loop in place of a for loop if possible.
  • You should avoid using ViewState to facilitate faster page loads. Remove the runat=”server” form tag from your Web page if you don’t need to use ViewState to save bytes of the page size. Enabling its ViewState would incur, for every byte that is added, becoming two bytes due to network traffic that is from the server to the client and the other from the client to the server.
  • Cache the Web pages or portion of the Web pages if the page is large. Use data caching for boosting the application performance instead of fetching data from a file or database.
  • As the datasets store data in memory, write efficient SQL queries or procedures that fetch only the information needed. Analyze the WHERE clause in your queries and be specific to ensure that the needed number of rows and columns are returned and take the advantage of indexes while writing queries.
  • Consider Using Server.Transfer instead of Response.Redirect because Response.Redirect sends a metatag to the client that makes the client send a new request to the server by using the new URL. Server.Transfer avoids this re-direction by making a server-side call.
  • Avoid using Page.DataBind. Instead, call data bind on specific controls because the page-level method in turn calls the DataBind method of every control on the page that supports data binding.
  • Minimize calls to DataBinder.Eval bercause this method uses reflection to evaluate the arguments that are passed in and to return the results. For example, if a page has a table with 50 rows and 10 columns, DataBinder.Eval will be called 500 times if you use DataBinder.Eval on each column. Instead, using explicit casting offers better performance by avoiding the cost of reflection. Cast the Container.DataItem as a DataRowView, as shown in the following code snippet.
<ItemTemplate>
   <tr>
      <td><%# ((DataRowView)Container.DataItem)
         ["First_Name"] %></td>
      <td><%# ((DataRowView)Container.DataItem)
         ["Last_Name"] %></td>
   </tr>
</ItemTemplate>

You can gain even better performance with explicit casting if you use a DataReader to bind your control and use the specialized methods to retrieve your data. Cast the Container.DataItem as a DbDataRecord.

<ItemTemplate>
   <tr>
      <td><%# ((DbDataRecord)Container.DataItem)
         .GetString(0) %></td>
      <td><%# ((DbDataRecord)Container.DataItem)
         .GetInt(1) %></td>
   </tr>
</ItemTemplate>
  • Disable unnecessary session states because ASP.NET Manages a session state by default and reduces the cost in memory when you don’t use it—like if your pages are static or when you do not need to store information captured in the page.
<@%Page EnableSessionState="false"%>
  • If session state is used only to retrieve data, make it read only.
       <@%Page EnableSessionState ="ReadOnly"%>
  • Turn off tracing unless required.
    <trace enabled="false" requestLimit="8" pageoutput="false"
       traceMode="SortByTime" localOnly="true">
    
  • Use SqlDataReader to visit the read-only data instead of DataSet.
  • Although you can return multiple resultsets by using dynamic SQL, it is preferable to use stored procedures to get multiple result sets.
  • Using gzip compression can decrease the number of bytes sent by the server. This gives the perception of faster page loads and also cuts down on bandwidth usage.
  • If you got a bunch of .NET Web services running in one IIS Application and consumed by another IIS application, the first call to Web services, in many cases, can be pretty slow, about 5 to 10 seconds or more sometimes; subsequent calls will be in milliseconds. To speed up the initial call, you can create the XmlSerializers DLL at compile time. You can do this by setting your project build ‘Generate serialization assembly’ to “On” as shown in Figure 1, in project properties.

ASP1
Figure 1: Setting the output path

This generates YourApplication.XmlSerializers.dll in the bin folder containing the Web service information to make the calls faster. Add the properties highlighted by editing the project file.

<PropertyGroup>
   <Configuration Condition=" '$(Configuration)' == '' ">Debug
      </Configuration>
   <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
   <ProductVersion>
   </ProductVersion>
   <SchemaVersion>2.0</SchemaVersion>
   <ProjectGuid>{9BB9E707-70A5-41C7-BB07-3F6C0F493388}</ProjectGuid>
   <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};
      {fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
   <OutputType>Library</OutputType>
   <AppDesignerFolder>Properties</AppDesignerFolder>
   <RootNamespace>EmployeeBank</RootNamespace>
   <AssemblyName>EmployeeBank</AssemblyName>
   <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
      <SGenUseProxyTypes>false</SGenUseProxyTypes>
   <SGenPlatformTarget>$(Platform)</SGenPlatformTarget>
   <UseIISExpress>true</UseIISExpress>
   <IISExpressSSLPort />
   <IISExpressAnonymousAuthentication />
   <IISExpressWindowsAuthentication />
   <IISExpressUseClassicPipelineMode />
   <SccProjectName>SAK</SccProjectName>
   <SccLocalPath>SAK</SccLocalPath>
   <SccAuxPath>SAK</SccAuxPath>
   <SccProvider>SAK</SccProvider>
   <UseGlobalApplicationHostFile />
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
   <DebugSymbols>true</DebugSymbols>
   <DebugType>full</DebugType>
   <Optimize>false</Optimize>
   <OutputPath>bin\</OutputPath>
   <DefineConstants>DEBUG;TRACE</DefineConstants>
   <ErrorReport>prompt</ErrorReport>
   <WarningLevel>4</WarningLevel>
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
<FilesToIncludeForPublish>AllFilesInProjectFolder</FilesToIncludeForPublish>
</PropertyGroup>

      <Copy
         SourceFiles="@(MySourceFiles)"
         DestinationFolder="$(WebProjectOutputDir)\bin"
            ContinueOnError="WarnAndContinue"
      />

Generate XmlSerializer serialization code for WCF services by using the following steps:

  1. Compile your service or client.
  2. Open an SDK command prompt and launch the Svcutil.exe tool. Use the following format:
    svcutil.exe /t:xmlSerializer <assemblyPath>

    The assemblyPath specifies the path to an assembly that contains service contract types. Svcutil.exe generates serialization code for all data types used in service contracts in the compiled application assembly that can be serialized using the XmlSerializer. Compile the generated serialization code into a separate assembly such as MyApp.XmlSerializers.dll and sign the application that uses this DLL with the same key as the original assembly.

  • Write common methods in the base class and inherit other classes from the base class to avoid repeated code.
  • You also can maintain a global library where common methods can be written. They then can be called in classes that do not inherit the base class for any reason or master page.
  • Maintain global constants in the application to avoid scattered constants across the application.
  • Stop throwing exceptions because they result in slowdowns; instead, log them using an effective logging method such as log4net or your own custom logging code and never use exceptions to control flow. You can add email configurations in web.config to send emails to developers, the QA team, or anyone based on the configuration when the application errors out.
  • Set debug to false in web.config before deployment.
  • Precompiling an ASP.NET Web site using the ASP.NET Compilation Tool (Aspnet_compiler.exe) improves the initial response time for users because pages need not be compiled the first time they are requested.

Conclusion

In my previous article, “ASP.NET Performance Improvements and VS2015 Profiler,” I showed how you can use the Visual Studio 2015 diagnostic tools that integrate application profiling with the debugging so that you can observe the CPU usage, memory usage, HTML UI responsiveness, thread activity timeline, and profiler for performance. By using what I presented in that article along with the optimization tips you’ve learned here, you have the tools for writing high quality code where you can catch and fix performance and other issues in development as well as after deployment.

About the Author

Sudha Polapragada works as a Lead Developer with a Government Agency. She spent lots of her programming years working as an ASP.NET programmer and with Microsoft Technologies. She also specializes in Oracle and the Microsoft BI suite. In her free time, she explores features on various development platforms, including various database, front-end technologies, Big Data, and cloud technologies.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read