Sponsored
Monday, May 1, 2017
Deploying a Web App from a Command Line using MSBuild and WebDeploy
Thursday, April 20, 2017
Finalized Agenda for the Global Azure Bootcamp 2017 Event
Tuesday, December 29, 2015
Easily add config transformation files to a Console App project
Friday, October 30, 2015
Using Google Tag Manager to deploy Azure Application Insights client-side monitoring
| If your web application is hosted on Microsoft Azure and you are using Application Insights for monitoring you'll have to add a piece of JavaScript on web pages to collect client-side statistics like page load time, JavaScript errors, users and sessions analytics, etc. The script can be found on Azure portal when Application Insights is enabled for a web application. |
Friday, September 19, 2014
404 Error in IIS for a Url with a plus + in the Path
www.somesite.com/one+two or
www.somesite.com/path/subpath/three+four
The behavior is considered a security feature and controlled by a setting called "Double Escaping Filtering". To override the default rejecting behavior the setting needs to be changed either via a web.config configuration:
<system.webServer>
<security>
<requestfiltering allowDoubleEscaping="true" />
</security>
</system.webServer>
or an IIS Management user interface:Thursday, July 24, 2014
Upgrade TeamCity to enable support for Visual Studio 2013
Symptoms
If you are using TeamCity in your development process and had upgraded from Visual Studio 2010 to VS 2013 in your development environment you may experience unexpected build errors on TeamCity if its version is lower than 8.1.x similar to the following:
error MSB4019: The imported project "C:\Program Files (x86)\MSBuild\Microsoft\
VisualStudio\v11.0\WebApplications\Microsoft.WebApplication.targets" was not found.
Confirm that the path in the declaration is correct, and that the file exists on disk.
The Story
The situation is that developers' work stations had been upgraded to Windows 8.x along with Visual Studio 2013 but a TeamCity build server still happily runs under Windows 2008 with .NET 4 installed and everything is just fine. Most likely the projects TeamCity builds target .NET 4.0 framework because they don't utilize newer features from .NET 4.5.x.
Next the decision is to switch your projects target framework to .NET 4.5 in order to take advantage of some new features, for example MVC 5, or ASP.NET Identity framework, etc. The projects have been successfully modified on developers' workstations and compiles and runs there but suddenly TeamCity is not happy because it cannot figure out how to properly build the project with the existing set of MSBuild tools. Apparently a build server software upgrade is required.
The Problem
In the error message above the key problem is that MSBuild is trying to import build targets from the wrong location "C:\...\MSBuild\...\v11.0\...". The exact problem is "v11.0" part. It comes from an environment variable that TeamCity sets when invokes MSBuild. The TeamCity sets it based on MSBuild tool version selected in its project definition. So technically it should be just enough to modify the MSBuild version to 2013 to fix the problem but TeamCity before 8.1.0 simply does not allow any other option to select from. Upgrade is required.
The Solution: Proper Build Server Set-up
Ideally a build server should resemble a production environment and should run the same versions of the build tools as developers have so obvious choice here is to install Windows 2012 with .NET 4.5 already on it and add Visual Studio 2013 build tools for compilation support. Then move TeamCity from the old build server to the new one and everything should be just fine. But there is a catch.
On the old build server TeamCity build steps have been configured to run MS Build v4.0 on .NET 4.0 Framework and MS Build would not be able to find required build targets because they are now in a different location corresponding to Visual Studio 2013. Installing Visual Studio 2013 in addition to the MS Build Tools 2013 would not help resolve the problem (and it's absolutely not required) since the problem is not with the .NET environment at all: the problem is that TeamCity does not know about Build Tools version 12.0.
To fix the problem TeamCity must be upgraded to the latest version but not below 8.1 because support for Visual Studio 2013 was added in version 8.1.0 and then all the build steps in all the projects should be modified to use a proper MSBuild version accordingly. Screen shots below illustrate the build step settings before and after the change:
Thursday, July 3, 2014
Cheat Sheet for Enabling Output Caching in ASP.NET MVC
What is Output Caching
ASP.NET output caching feature allows increasing web application performance by returning content that was built some time ago instead of rebuilding it on every request. Returning content from cache only takes a few milliseconds as opposed to executing a full request cycle that could take much longer.
The content is being cached on the ASP.NET level and the request would not reach the application code for the content that is still in cache. ASP.NET output caching can be used in both WebForms and MVC applications and using it in MVC has become even easier than before.
When to use Output Caching
Output caching is useful when content returned by a controller action method does not change frequently, requires more than few CPU cycles or database access and does not require a lot of memory to store. For example, I would not recommend to use output caching for a large binary object like an image or a file. Also there is no point to cache a short string that only takes a few milliseconds to build. The best use case would be an average size content that requires some calculation or database access to produce but does not change on every request.
How to enable Output Caching
The easiest way to enable output caching in MVC is using an OutputCache attribute on the controller or controller action method. Applying output caching on a controller action method is recommended as it gives much better granularity and control over output caching. The best way to control output caching behaviour is via caching profiles that allow defining all parameters in a web.config file and override them for each environment where the web application is deployed (i.e. Dev, QA, Stage, Live, etc.)
Limitations
ASP.NET MVC has some limitations for output caching, for example: caching profile is not supported for a partial/child controller method therefore caching parameters including Duration and VaryByParam must be set in the code.
Implementation and code review check points
- Apply to individual action methods
- Use Caching profiles
- Partial/child action methods should not be cached for too long
- Disable output caching in Dev/QA/Stage environment.
- Do not forget to set Duration and VaryByParam values in web.config
Example
<system.web>
<caching>
<outputcachesettings>
<outputcacheprofiles>
<add name="cacheProfile" duration="60" varyByParam="*" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>
[OutputCache(CacheProfile = "cacheProfile")]
public ActionResult Test()
{
ViewData["result"] = "This text was rendered at " + DateTime.Now;
return View();
}
Thursday, November 7, 2013
Setting Cache Control HTTP Headers in Web API Controller Method
Basically in order to control caching behaviour we need to make sure that the output response will have what is called "Cache control header" with proper values that determine caching behaviour. Example below demonstrates how to make a response publicly cacheable for a period of time:
var response = new HttpResponseMessage();
response.Headers.CacheControl = new CacheControlHeaderValue
{Public = true, MaxAge = TimeSpan.FromSeconds(maxAge)};
To simplify the usage further we can even create a static extension method that can be easily applied in a controller method:
// somewhere in a static class
public static HttpResponseMessage PublicCache(this HttpResponseMessage response, int maxAge)
{
response.Headers.CacheControl = new CacheControlHeaderValue
{Public = true, MaxAge = TimeSpan.FromSeconds(maxAge)};
return response;
}
...
// inside an ApiController class
public HttpResponseMessage MyApiMethod(long id)
{
var response = new HttpResponseMessage();
..............
return response.PublicCache(24 * 7 * 60);
}
Monday, December 10, 2012
Setting a "Content-Disposition" HTTP Header in Web API Controller Method
There are two different ways to approach this simple task. First is to add a new HTTP header to the HTTP response using string values for the header's name and value. The second is to try and use the .NET framework's infrastructure methods that presumably should make this task easier.
The first method seems to be very simple but potentially dangerous: one would need to hard-code string values and be totally responsible for the values to be properly formatted according to the W3C standards.
var response = new HttpResponseMessage();
response.Headers.Add("Content-Disposition", "attachment; filename=fileName.ext");
The second method is to try and delegate handling of the specifics of the HTTP protocol to the .NET framework by using corresponding presumably built-in methods. This seems more appropriate and even easier to achieve. However due to poor documentation of the Web API extensions that is easier said than done. without further ado this is how it's done:var response = new HttpResponseMessage();
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment") { FileName = fileName};
Only one string value here should hard-coded with a guideline available in the official documentation so it's not that bad.If you find this information possible share it with your fellow colleagues so it may save their valuable time.
Saturday, November 5, 2011
Using Anonymous Types Outside of Local Context with Dynamic Keyword
Anonymous types that have been introduced in C# with .NET 3.5 is a convenient and powerful feature and can be used to simplify and speed up development without sacrificing code quality or violating coding standards.
Tuesday, July 12, 2011
Using jQuery to Consume ASP.NET MVC JSON Services
Since the inception of ASP.NET Web Services have been an important part of any professional web developer's tool set. Starting .NET 3.5 Web Services became even more useful as it became possible to call Web Services asynchronously from a browser using JavaScript and ASP.NET AJAX.
However for the last two years the alternative ASP.NET MVC framework has been drawing more and more attention from the development community due to its good implementation of the MVC design pattern and adherence to web standards and bleeding edge web technologies.
For many experienced ASP.NET developers accustomed to Web Services especially accompanied with ASP.NET AJAX framework a natural question occurs: how to implement similar approach with ASP.NET MVC framework and its natural JavaScript companion jQuery?
Sunday, May 1, 2011
Fix for Bing Maps not working in Firefox 4+
Apparently that problem exists for Firefox 5 also and perhaps will apply for the future versions too. So the solution below should be considered a best practice for using Bing Maps 6.x with Firefox 4+.
Recently I've upgraded from Firefox 3.6 to Firefox 4 and while doing regression testing I've notice that apparently Bing Maps has some issues in Firefox 4. In particular I saw a JavaScript error that said "p_elSource.attachEvent is not a function":
The problem at this point looks like this:
- the error happens in Bing's JavaScript itself; and
- it only happens in Firefox 4 browser. Other browsers like IE 8 & 9, Chrome, Safari, Opera and Firefox 3.6 don't produce that problem.
What's that condition? I looked at the difference between Firefox browser and the other browsers. When in Firefox Bing Maps dynamically loads another JavaScript file atlascompat.js. Apparently that file is required since it contains a definition for the attachEvent function that caused an error and must be loaded first before the main Bing Maps script. So that's the condition I've been looking for! Now the picture got clearer:
- the error happens in Bing's JavaScript itself; and
- it only happens in Firefox 4 browser. Other browsers like IE 8 & 9, Chrome, Safari, Opera and Firefox 3.6 don't produce that problem;
- it happens when the atlascompat.js is not present on a page at the moment when the main Bing Maps script is being loaded.
The solution is simple: since the Bing Maps itself cannot load the atlascompat.js reliably I need to help it and just add a reference to the atlascompat.js script on my page before a reference to the main Bing Maps script. This can be easily accomplished with a few line of code like below:
if ((Page.Request.Browser.Browser.IndexOf("Firefox") >= 0) && (Page.Request.Browser.MajorVersion >= 4))
{
// add script reference on a page
// use technique that is suitable for your application
}Notice that the browser version is more or equal 4 to cover the future versions of Firefox too (for version 5 this solution is confirmed). In my case I've added the code above into a GetScriptReferences method of an IScriptControl that was responsible for rendering the Bing Maps on a page.
Friday, February 11, 2011
.NET Reflector is becoming a paid-for product
For those who do not remember the .NET Reflector was born in the beginning of 2000s and has quickly become one of the must-have tool for every serious professional .NET developer. A large users community has quickly formed around the tool and many great add-ons have been written by inspired developers. Reflector has influenced great many developers' careers and earned community recognition. Scott Hanselman included the program in his "Ultimate Developer Tool List".
The Reflector's success was growing for over half a decade when out of a sudden the original author of .NET Reflector announced about his decision to stop developing the product and give it over to Red Gate Software in August 2008. One part of the agreement was that
...Red Gate will continue to provide the free community version... [of .NET Reflector]confirmed by James Moore of Red Gate Software but many had skepticism about that part of the agreement from the very beginning.
During the period of Red Gate's ownership there were not many real improvements to the Reflector except for the annoying built-in "time-bomb" feature forcing one to upgrade to the newer version of the product even though the installed version worked perfectly. Some time ago a paid-for "Pro" version was announced with an obvious reason to raise some money for the owner but based on the Red Gate's plea was not successful among developers. One of the suggested explanations for that is that paid-for functionality was not really of any interest (more creativity, please, Red Gate) for professionals and beside there were already free add-ons doing similar things.
So now Red Gate wants to charge $35 for "a perpetual license, with no time bomb or forced updates" for the version 7 that will come out in early March and promises some new features in V7.
Red Gate claims that they need money to "keep .NET Reflector up-to-date and relevant" and cannot do that "without revenue coming in". That may be true for the Red Gate Software but there is a proven recipe for that: how about make the product open source, put it on Code Plex or any other similar location and let the community take care of its relevancy? To make it even more interesting let's make it a challenge: you, Red Gate, charge for your new shiny V7 but give away the previous version to the open source community and let's see which version survives in a few years. I personally have no doubts on the results.
There is a discussion going on about the Reflector's future on Red Gate's user forum. However if you are a professional developer that uses and loves Lutz Roeder's Reflector I encourage you to share your opinion and vote for the Reflector's future right here in my blog on the right side or answer polls on LinkedIn here and here. Please share the poll with your friends and colleagues.
UPDATE
Interesting list of open-source alternatives to Reflector on Stack Overflow: http://stackoverflow.com/questions/2425973/open-source-alternatives-to-reflector
To my taste the closest to .NET Reflector user experience is provided by the ILSpy. I am going to try and compare it with the Reflector.
Another UPDATE of May 1, 2011
Apparently free Reflector's lifespan is going to end on May 30, 2011. Today I've started my free copy and saw this alert:
UPDATE of May 31, 2011
Free version of Reflector is finally dead. Now those who does not want to switch to a paid version has to consider alternatives. A couple of new alternatives include:
JustDecompile
Telerik has recently released a beta version of their new JustDecompile, designed to enable easy .NET assembly browsing and decompiling. While Telerik is not know for free software, this product is featured as being free. According to Telerik, "Unlike Open Source alternatives, Telerik JustDecompile benefits from a dedicated development team, which is focused on continuously improving the product in line with your feedback. Telerik is recognized as one of the leading providers of .NET development tools and JustDecompile will benefit from our years of experience in the field."
dotPeek
JetBrains, an author of an extremely popular ReSharper Visual Studio add-in, has recently released a beta version of the dotPeek which is another new and free .NET decompiler with search features from JetBrains. dotPeek has gone public for the first time on Wednesday, May 11, as JetBrains opened an Early Access Program (EAP) that implied regular publishing of pre-release builds. According to JetBrains they are going to keep the product free.
Final Thought
JetBrains dotPeek has become my tool of choice for the time being. It's functional, free and being updated frequently. For those who also uses JetBrain's ReSharper starting version 6 the dotPeek functionality is built-in and available through the Navigate/To Decompiled Source menu.
Tuesday, December 28, 2010
Set up local SMTP for your .NET development environment on Windows 7
If you are developing a .NET application that sends emails then you need a way to do that without needing to actually send emails out. On Windows 7 with IIS 7 installed you can easily configure a local SMTP service that will intercept all the SMTP sessions initiated in your code and successfully emulate sending the outbound email by saving it as a text file in a folder on your local hard drive. This is extremely convenient and allows you to keep working on your code without interruption even when you are not connected to the Internet.
To achieve that just add a few lines in your application's .config file (could be web.config or app.config). Here is an example of such a configuration:
<system .net="">
<mailsettings>
<smtp deliverymethod="SpecifiedPickupDirectory">
<specifiedpickupdirectory pickupdirectorylocation="c:\smtp">
</specifiedpickupdirectory></smtp>
</mailsettings>
</system>
After adding such a configuration every time your application sends an e-mail using a .NET framework built-in SmtpClient.Send method a new file with the .eml extension will appear in the configured folder.
You can open a file with any text editor like Notepad++ for example or you can use this free EML Viewer to improve viewing experience.
Friday, May 7, 2010
How to set programmatically a value of a watermarked TextBox via JavaScript - Update
Ajax Control Toolkit changes
One of the most significant changes in the recent Ajax Control Toolkit release that affected everything is renaming namespaces and control names. Most of the JavaScript classes in the ACT has been moved into Sys.Extended.UI and some of them renamed.Correspondingly the AjaxControlToolkitTextboxWrapper class that is crucial for the technique described in this article is now called Sys.Extended.UI.TextBoxWrapper and this is a breaking change. Most if its methods haven't been renamed and this is a good news however the new way of using the wrapper has been introduced.
Below are the code examples demonstrating how to write the code correctly with the new version of the ACT.
First we need to acquire an instance of the Sys.Extended.UI.TextBoxWrapper class for our textbox control and this is the newly introduced technique compared to the previous version of the ACT:
// get the instance of a textbox element
var textBox = $get(textBoxId);
// use the get_Wrapper static method of the TextBoxWrapper class to get the instance of the wrapper for the textbox
var wrapper = Sys.Extended.UI.TextBoxWrapper.get_Wrapper(textBox);
In the code above first I assume that the ACT is present so I don't have to check that Sys.Extended.UI namespace is defined. Secondly the code above is safe even if the textbox is not watermarked: the get_Wrapper static method will always return the instance of the TextBoxWrapper; the new instance will be created if the textbox is not watermarked.
Now we can set or get a value of the textbox using the instance of the TextBoxWrapper:
// get the textbox value
var oldValue = wrapper.get_Value();
// set the textbox value
wrapper.set_Value(newVlaue);
Conclusion
In a nutshell there are two major changes introduced in the new ACT release that affect the coding technique described here: the name of the textbox wrapper class has been changed; and now it's not required to check whether the textbox is watermarked to use the technique above.Wednesday, May 5, 2010
Leveraging Visual Studio JavaScript IntelliSense.
One of the most useful features of the Visual Studio 2008 and Visual Studio 2010 is JavaScript IntelliSense that allows developers write JavaScript code faster, with fewer errors and reduce learning time of some JavaScript frameworks. Many developers already enjoy its power when code JavaScript with Microsoft ASP.NET Ajax framework and jQuery. However many developers are still not familiar with that tool and even less developers realize that it can also be used with their own code.
Sunday, November 29, 2009
Automatically compress embedded JavaScript resources with Microsoft Ajax Minifier
The question however is how to use it. Microsoft Ajax Minifier package does include a set of documentation that explains how to use the tool and even discusses a couple of usage scenarios. Unfortunately the way I wanted to use the Minifier is not covered in the documentation and for some reason I haven't found useful information on the Internet too so I've decided to do some research and share my findings with the community.
So how would I like to use the Minifier? Here are the requirements:
- I want to automatically compress embedded JavaScript resources in any project of my web application solution.
- I want the compressed JavaScripts have the original names so I don't have to change the references in HTML mark-up.
- I want the compression to be done only when I switch to the Release mode in Visual Studio. When I am in the Debug mode I want all the JavaScript files to be uncompressed for easier debugging.
- I want compressed JavaScript files never overrides the original JavaScript files and I don't want to keep the compressed JavaScripts so whenever I modify my JavaScript code the compressed resources are always up-to-date.
I believe that the requirements above describe one of the most common web application solution configuration so if there is a way to achieve them it would be very useful.
Can I achieve the requirements above with the Microsoft Ajax Minifier? The answer is yes. The solution is kind of obvious: since the Microsoft Ajax Minifier includes an MSBuild task I just need to modify a project file where I have embedded JavaScript resources that I need to be compressed to include the Microsoft Ajax Minifier build task. It does not sound complicated and below is the solution which is simple indeed. Just include the following XML in your project file right before the closing </Project> tag (in most cases):
<!-- Minify all JavaScript files that were embedded as resources -->
<Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks" />
<PropertyGroup>
<ResGenDependsOn>
MinifyJavaScript;
$(ResGenDependsOn)
</ResGenDependsOn>
</PropertyGroup>
<Target Name="MinifyJavaScript" Condition=" '$(ConfigurationName)'=='Release' ">
<Copy SourceFiles="@(EmbeddedResource)" DestinationFolder="$(IntermediateOutputPath)" Condition="'%(Extension)'=='.js'">
<Output TaskParameter="DestinationFiles" ItemName="EmbeddedJavaScriptResource" />
</Copy>
<AjaxMin SourceFiles="@(EmbeddedJavaScriptResource)" SourceExtensionPattern="\.js$" TargetExtension=".js" />
<ItemGroup>
<EmbeddedResource Remove="@(EmbeddedResource)" Condition="'%(Extension)'=='.js'" />
<EmbeddedResource Include="@(EmbeddedJavaScriptResource)" />
<FileWrites Include="@(EmbeddedJavaScriptResource)" />
</ItemGroup>
</Target>
What this script does is when the solution configuration is 'Release' it finds all the project embedded resource files with the extension '.js' and creates their compressed versions with the same names in the intermediate output folder where they are picked from later by the build process.
A few tips
As you may have noticed the Microsoft Ajax Minifier MSBuild task is referenced from the default folder where it was copied to by the installer. If you want to reference it from a different location, for example if you have a shared development environment and want to have similar setting for everyone, just copy two files ajaxmin.dll and ajaxmintask.dll to another location and include the <UsingTask> tag (below) instead of the <Import> tag in the script above:
<UsingTask TaskName="AjaxMin" AssemblyFile="$(MSBuildProjectDirectory)\..\Build\AjaxMinTask.dll" />
The presented script performs so called 'Normal Crunching' (see the Ajax Minifier documentation) of the JavaScript code which already does a pretty good job that is good enough in most of the cases: compression rate is over 50%. If you would like to turn on the 'Hypercrunching' mode (see the Ajax Minifier documentation) you only need to modify one line of the script to include the 'LocalRenaming' option of the Ajax Minifier:
<AjaxMin SourceFiles="@(EmbeddedJavaScriptResource)" SourceExtensionPattern="\.js$" TargetExtension=".js" LocalRenaming="CrunchAll" />
And the last note is: don't use the default Hypercrunching mode or RemoveUnneededCode option with the ASP.NET AJAX Framework as it does not work properly with it.
Thursday, November 19, 2009
Using the Microsoft Ajax Library 3.5 with the CDN
Recently Microsoft has announced its Microsoft Ajax content delivery network (CDN) which can significantly improve the performance of any ASP.NET AJAX web application. When it was first announced the CDN was almost useless for the current web applications based on ASP.NET 3.5 since it did not host the Microsoft Ajax library 3.5 and did not support content delivery via SSL. However in a very short period of time Microsoft was able to fix those problems (good job!) and now web applications built on ASP.NET 3.5 can benefit from using Microsoft Ajax CDN.
So how do you make MicrosoftAjax.js file being referenced from the CDN as opposed to the embedded file? Quite easy actually with the help of the ScriptManager control. Add the following declaration to a page (or Master page) where there is a ScriptManager control:
<asp:scriptmanager runat="server" enablepartialrendering="false">
<scripts>
<asp:scriptreference name="MicrosoftAjax.js" path="http://ajax.microsoft.com/ajax/3.5/MicrosoftAjax.js" />
</scripts>
</asp:ScriptManager>
What that declaration means is that the script with a name MicrosoftAjax.js which is always automatically referenced by a ScriptManager from the System.Web.Extensions dll now should be referenced from that location: http://ajax.microsoft.com/ajax/3.5/MicrosoftAjax.js.
This is how it is referenced by default:
<script src="/ScriptResource.axd?d=eYUqBJhfSVL41hIDYkBL0tfaps9hoQId_48PydfbcyWH41vNvL68sk-l7P9FLAPz7b4vtI8WkZ-ezAF0b_ZkyG52wt9oUtaQ5ezFfGBr7LY1&t=ffffffffef976216" type="text/javascript"></script>
and after we include the new ScriptReference declaration:
<script src="http://ajax.microsoft.com/ajax/3.5/MicrosoftAjax.js" type="text/javascript"></script>
ScriptManager is even smart enough to automatically reference the debug version MicrosoftAjax.debug.js from the CDN when debugging is enabled in the web.config file:
Web.config:
<compilation debug="true">
HTML:
<script src="http://ajax.microsoft.com/ajax/3.5/MicrosoftAjax.debug.js" type="text/javascript"></script>
So this is clear: we have our MicrosoftAjax.js referenced from the CDN and that improves our web application performance and saves us and the visitors some bandwidth since an internet browser will reuse the same cached copy of the MicrosoftAjax.js from the CDN for different web applications that reference it.
Using the CDN conditionally
What if we only wanted to reference MicrosoftAjax.js from the CDN when the web application is deployed to a production environment and use an embedded version in a development environment? That would make sense in order for the developers to work without having to be connected to the Internet. Once again it can be done but this time we'll need to write some code. We are going to add the MicrosoftAjax.js script reference dynamically depending on the debug value in the web.config file; we only add the script reference when debug="false":
protected void Page_Load(object sender, EventArgs e)
{
if (!Context.IsDebuggingEnabled)
{
ScriptManager sm = ScriptManager.GetCurrent(this);
sm.Scripts.Add(new ScriptReference
{Name = "MicrosoftAjax.js", Path = "http://ajax.microsoft.com/ajax/3.5/MicrosoftAjax.js"});
}
}
Using the CDN via SSL
Another major case is when our web application has pages that are served via SSL. In this case we want to automatically select the correct CDN URL for the MicrosoftAjax.js. In order to do that we just modify the previous code:
protected void Page_Load(object sender, EventArgs e)
{
if (!Context.IsDebuggingEnabled)
{
ScriptManager sm = ScriptManager.GetCurrent(this);
sm.Scripts.Add(new ScriptReference
{Name = "MicrosoftAjax.js", Path = Request.Url.Scheme + "://ajax.microsoft.com/ajax/3.5/MicrosoftAjax.js"});
}
}
So that's it for now. Enjoy using the Microsoft Ajax CDN.
Monday, April 27, 2009
How to Improve ASP.NET UpdatePanel Performance
Since ASP.NET AJAX UpdatePanel was first introduced it has earned a strange mix of reputation. From one hand it has become a tool of first choice for many ASP.NET developers who wanted an easy way of introducing an AJAX-like behavior for their ASP.NET web apps. From another hand it has earned a lot of criticism from seasoned web developers because of certain performance consequences associated with complex usage scenarios.
Well, everything may be good and may be evil based on how we use it. From my experience consious and judicious use of UpdatePanel is the key to saving its benefits and avoiding potential problems.
Below I suggest a number of rules that help achieving better results when using UpdatePanel.
- Avoid automatic refreshing of UpdatePanel; always stay in control of which UpdatePanel and when refreshes: set UpdateMode property to Conditional (the default value is Always).
- Minimize the content of the UpdatePanel: the
<ContentTemplate>should only include controls that are neccessary to refresh. For instance if user input requires server-side validation include only an error message mark-up in the UpdatePanel and leave the rest of the form outside. - Try to keep the partial postback trigger controls outside of their respective UpdatePanels unless its neccessary to change their markup.
- Try to stick to a simple rule: one trigger for one UpdatePanel. If you need to refresh multiple UpdatePanels during one request add a trigger control to only one of those UpdatePanels and refresh the others programmatically in an event handler on the server. The idea is to avoid uncontrollable refreshing of unnecessary UpdatePanels.
- Since ViewState is updated with every partial postback request turn the ViewState off on a page that contains the UpdatePanel wherever possible or store the ViewState on the server to avoid transferring it forth and back with every async request.
- Since Page runs through its lifecycle during every partial postback and executes methods like Page_Load or Page_PreRender make sure that logic that is unneccessary for refreshing UpdatePanel is not executed by wrapping it in
if(!ScriptManager.IsInAsyncPostBack). - If you use UpdatePanel event handlers like Init, Load, PreRender and Unload make sure that code inside these event handlers does not execute unless neccessary by checking
Page.IsPostBackandScriptManager.IsInAsyncPostBackproperties. - If you trigger an UpdatePanel programmatically from the client-side (via JavaScript) make sure that its event handler check for the event trigger value using
Request.Params["__EVENTTARGET"]ot avoid unnecessary execution path. - If you programmatically update Page's Header (Title, etc.) or other Page's content that is outside UpdatePanel make sure that this code never gets executed during partial postbacks. First of all its not neccessary since page does not refresh but also it may be dangerous because the content may not be handled properly by a browser.
Conclusion
There may probably be more tricks and tips regarding usage of UpdatePanel but those mentioned above have been proven by real exeprience. I would also recommend understanding how UpdatePanel works behind the scene and never hesitate using Fiddler to investigate what your web app's doing.
Friday, May 23, 2008
ScriptManager vs. ToolkitScriptManager
Introduction
ScriptManager is a special ASP.NET server control that should be placed on a page before you can use any of AJAX.NET enabled controls. The same rule is true for the AJAX Control Toolkit controls: they all require a ScriptManager on the page. While AJAX Control Toolkit controls work perfectly fine with the standard ASP.NET ScritpManager the Toolkit includes its own version of the ScriptManager called ToolkitScriptManager that inherits from ScriptManager and is meant to improve some of the ScriptManager's behaviors in particular how it renders out behavior JS scripts. Let's examine how using a ToolkitScriptManager changes a web page's appearance.
Experiment
As a testing example I have created a very simple page consisting of a single Accordion control from the AJAX Control Toolkit library.
<head runat="server">
<title>Untitled Page</title>
<style type="text/css">
.accHead { border:1px solid #445566;font-size:larger;background-color:#aaa;}
.accHeadSel { border:1px solid #445566;font-size:larger;background-color:#444;color:#fff;}
.accCont { border:1px solid #ccc;padding:5px;}
</style>
</head>
<body>
<form id="form1" runat="server">
<ajax:ToolkitScriptManager ID="tsm" runat="server"></ajax:ToolkitScriptManager>
<%-- <asp:ScriptManager ID="sm" runat="server"></asp:ScriptManager>--%>
<div>
<ajax:Accordion
ID="MyAccordion"
runat="Server"
SelectedIndex="0"
HeaderCssClass="accHead"
HeaderSelectedCssClass="accHeadSel"
ContentCssClass="accCont"
AutoSize="None"
FadeTransitions="true"
TransitionDuration="250"
FramesPerSecond="40"
RequireOpenedPane="false"
SuppressHeaderPostbacks="true">
<Panes>
<ajax:AccordionPane ID="AccordionPane1" runat="server"
HeaderCssClass="accHead"
ContentCssClass="accCont">
<Header>Pane Header 1</Header>
<Content>Content 1</Content>
</ajax:AccordionPane>
<ajax:AccordionPane ID="AccordionPane2" runat="server"
HeaderCssClass="accHead"
ContentCssClass="accCont">
<Header>Pane Header 2</Header>
<Content>Content 2</Content>
</ajax:AccordionPane>
<ajax:AccordionPane ID="AccordionPane3" runat="server"
HeaderCssClass="accHead"
ContentCssClass="accCont">
<Header>Pane Header 3</Header>
<Content>Content 3</Content>
</ajax:AccordionPane>
</Panes>
<HeaderTemplate>List of Panes</HeaderTemplate>
<ContentTemplate></ContentTemplate>
</ajax:Accordion>
</div>
</form>
</body>
You may have noticed that right after the form tag there are ScriptManager (SM) control and ToolkitScriptManager (TSM) control on the page but one of them is commented out. Next I run a page from VS 2008 two times: first using the SM and second using TSM, and compare the results.
HTML output and traffic
Let's compare the HTML output of two page versions. See a WinMerge screen shot below that shows the SM version in the left pane and the TSM version in the right pane.
First difference you see is that TSM adds its own hidden field on the page (top right pane) and the next and more important difference is that TSM renders one script reference on the page instead of the five ones that SM does.
Now if we examine the page's traffic with the FireBug we'll see how that changes the traffic: first graph refers to the page using the SM control and the second one when the TSM's at work.
Analyzing the graphs it's easy to see that the TSM does reduce a number of browser's round-trips by combining multiple script references into a single one. This advantage will become more attractive as more AJAX-enabled server controls will be placed on a web page that support script combining. However it is not necessarily true that it will always reduce the page loading time. As you can see when TSM returns a combined script to the page it takes some time to perform a work on the server. Correspondingly the amount of work and consequentially the response time directly depend on the number of scripts to combine (that is a number of AJAX server controls) and the size of the scripts to process (white spaces removal and compressing).
So there is no single recommendation that it's always preferable to use TSM instead of SM. In many cases SM version of a page may work faster then a TSM version of the page. Since it's not that difficult to alter a page for both cases I'd advise to test and compare both versions in your particular scenario before making a decision which one to choose.














