July 2007 Entries
Update : February 27, 2008
Mentioned the location where the MSI File gets created in case of Websetup Deployment owing to a lot of queries on the same in the comments.
Update: February 21, 2008
Posted a Video version of this article
Well, you developed a web application. You need to deploy it. With ASP.NET (1.x versions), Visual Studio .NET provided simple way to create setup files for your web applications to make it install as if it were a stand alone application. The whole process was simplified when using Visual Studio .NET 2003's Setup and Deployment Wizard. So with ASP.NET 2.0 and Visual Studio 2005, what is new and what are the different Deployment Models available? Let us explore them one by one.
Web Setup Deployment - Creating an installer file
This option hasnt changed a lot when compared with Visual Studio .NET. Let us explore the steps.
1. Open your website in Visual Studio 2005
2. Right Click on the Solution Name (Solution 'Your solution') and select "Add - New Project". The "Add New Project" dialog appears. Select "Other Project Types" and expand the same. Select "Setup and Deployment" and in the available Templates select "Web Setup Project" and provide a name ex. "WebSetup1" to create the project in the location of your choice
3. Right Click on the "WebSetup1" created above and choose "Add - Project Output" You would be able to see it lists out the available project in the "Project" dropdown. The only option you would find here is "Content Files". Here is where you find the difference. In Visual Studio .NET and ASP.NET 1.x verions you would need to add "Primary Output" option which is the assembly created for your Website. Here in ASP.NET 2.0 there is no default Website Assembly (in other words DLL File and BIN Folder) unless you explicitly create a BIN folder. Hence you just need to select "Content Files" which will bundle up ASPX, Codebehind, Resource Files, Images, Folders etc., Thereafter you can choose to add a "ReadMe.txt" or something that you require by again choosing "Add" but I leave it you as it is completely optional.
Once you are done with adding the required Project Output, Right Click on the "WebSetup1" project and "Build" it. It would create the installer file (MSI File) that can be used for installing your application on different machines.
Make sure you select "Release" Mode in Visual Studio 2005 before creating the Web Setup since that would optimize the binaries for performance.
A lot of people get back to me saying that they couldnt find the MSI File Created. There are two reasons why your MSI file creation was unsuccessful.
1. You chose File - New Project - Setup and Deployment instead of File - Add New - Project - Setup and Deployment. The former one creates a new project with just a websetup. The latter creates the web setup project under the same solution and allows you to add the website output to the web setup
2. The MSI File typically C:\Documents and Settings\<username>My Documents\Visual Studio 2005\Projects\<your Web Project folder> This is even if you had created the website in c:\inetpub\wwwroot because the Solution File typically gets created in the C:\Documents and Settings\<username>My Documents\Visual Studio 2005\Projects\ path unless you modify it. A lot of us could just over see it when creating the project/solution and generally we dont need the solution file so dont bother to look for it. In the case of deployment the MSI File also sits in the same location where the solution file is created and hence this step would help you identify the same.
Website Publish Wizard Deployment
Visual Studio 2005 also provides you with a new "Web Publish Wizard" option where you can publish your websites files to a different machine / directory to a HTTP / FTP or a file share of your choice. Exploring the steps
1. Right Click on your Web Project and select "Publish Web Site". It will prompt you with a "Publish Web Site" dialog where you can specify the path to be published. You can do a variety of options like "Allow this precompiled site to be updatable". What it means is that, the website is precompiled and the codebehind source get into a BIN directory that is created.
2. The ASPX pages, Images etc., and other markup files are copied to the location specified AS IS.
3. You would also find a PreCompiledApp.Config file.
This option is pretty handy if you keep updating the site to a Staging Server on a regular basis since it wouldnt be feasible to create an MSI installer everyday / everytime you want to deploy your files.
Copy Website Deployment
The Copy Website provides you an option to simply copy the source files to a destination folder which can either be on your local machine or an FTP / HTTP Location. The difference in this case is that, the Website is not precompiled. Your Website is copied AS IS and all the files include the code behind files are copied to the destination. However, the Copy Website Deployment does more than merely copying them. When you use Copy Website option it shows the status of the files in the Source and Destination location and you can synchronize them using the "Synchronize" option that would help you maintain similar versions in different locations. Steps herebelow
1. Select your Website Project, Right Click and select "Copy Website"
2. It provides with you an interface listing the "Source" in the left and provides you the option to "Connect" using the "Connect" option to specify the destination. However, it can also be vice versa since you can select "Source" to be your destination location and do a copy back to your local folder as well.
3. The "Synchronize" button helps you to keep the files synchronized. There is also a Log that is created which can be viewed from this interface. In simple terms Copy Website Deployment is deploying the files as is with source/destination file synchronization.
PreCompiled Web Deployment
With all of these options above, you also can manually precompile the whole application using the PreCompilation tool installed with ASP.NET 2.0. Steps herebelow:-
1. Type "cmd" from Run command to open the Command Prompt
2. Navigate (Change Directory - cd) to %windir%\Microsoft.NET\Framework\v2.0.50727
3. Type aspnet_compiler -v /"Your Website Name" -p "Physical Path to your site" "Physical Path to Deployment Location"
4. An ideal example of above would be aspnet_compiler -v /Website1 -p "D:\Projects\Website1" "D:\PreComiled Website1"
5. There are multiple switches which you can try in the above command. You can verify all the options by typing aspnet_compiler -? from %windir%\Microsoft.NET\Framework\v2.0.50727\
Once you run the above command you would notice that in the Deployed location, all the files including ASPX, ASCX are precompiled and dont contain any markup. If you try opening an ASPX Page, you will only find the text "This is a marker file generated by the precompilation tool, and should not be deleted!" and it doesnt contain any HTML markup. This way the site is totally precompiled and can also prevent any one from viewing the source code. You need to specify the "-u" keyword in the above command before the target directory specification, to make this site updatabale.
When to choose what?
Ok, we saw a variety of options on how we can deploy ASP.NET 2.0 applications and a variety always brings in question on when to use what.
While it is absolutely specific to your customer needs or personal preference, an informal thumb rule I would suggest is as follows.
1. Web Setup Installer for major releases which are not frequently updated.
2. Publish Website for day to day update and staging servers where you want source code (code behind / App Code) contents to be concealed by precompiling.
3. Copy Website where you want to do day to day update and synchronization with staging servers where you dont worry about source code being able to be viewed. In other words a simple X Copy with synchronization features.
4. Precompilation using the aspnet_compiler command utility when you want to precompile both the source as well as markup files seeking high performance, security features.
In this article we saw various options for deploying ASP.NET 2.0 Applications. I hope you found it beneficial. If you have queries please post in comments.
The following articles also provide more information on customizing the ASP.NET 2.0 MSI Deployment Model
While I have been writing a lot about ASP.NET AJAX and other stuff, I also wanted to keep adding my little nuggets on ASP.NET 2.0 which is one of the favourite platform for Web Development. While working with ASP.NET 2.0 and Visual Studio 2005, you may not know certain new things which are a part of it and usually go unnoticed. Atleast I missed them and after a year, completing a big application realized that it would have been great if I had used these features.
So, here it is, 10 things you might not know about ASP.NET 2.0
No need to press "Ctrl + Shift + B" (Build) for everything
When working with ASP.NET 2.0 and Visual Studio 2005, you dont need to press Ctrl + Shift + B (in other words build) to check every change you make to the source / design. Both the ASPX Page and Code behind files are compiled dynamically when you run the page and if there is a change, the source / design is recompiled accordingly so you dont have to rebuild the solution. In fact the only instance where you want to rebuild the solution is when you add an external DLL reference / modify and add an external DLL again, where I have found some cases when the change is not reflected.
This would save a lot of time particularly in big projects where you have lot of source files and building all of them for each and every change would consume lot of time.
Data Source doesnt always need to be SQL DataSource
When working with Data Sources most of us would have seen the SQL Data Source examples and always said "Ah, this is good for Demo but what about enterprise applications where I cannot have the SQL Query or Stored Procedure mentioned in the Data Source definition in the ASPX Page" Object Data Source accepts your business layer methods as inputs and very well acts as a bridge between your business layer.
Web.Config is more friendly to IIS
Web.Config is one of the favourite things and the toughest nuts to crack in terms of editing them. While most of us might have seen Web.Config edited using the Website Administration Tool (if it sounds like alien to you or have never tried out, go to "Website - ASP.NET Configuration" in Visual Studio 2005), little is known that you can edit the Web.Config settings using IIS - yes Internet Information Services.
When you install ASP.NET 2.0 (gets installed when you install Visual Studio 2005 as in most of the cases), you get the "ASP.NET" Tab for virtual directory properties and that provides you a whole bunch of utilites like version management as well as Configuration management wherein you edit the Web.Config properties, very handy for deployment scenarios where you dont have Visual Studio 2005 and hence no Website Administration Tool.
Client Script Call Back allows you to AJAXify your page
While the whole world is running behind installing AJAX Toolkits including ASP.NET AJAX, ASP.NET 2.0 had this little nice feature called "Client Script Callback Manager" which allows you to make asynchronous calls to your server side methods and hence enabling partial page update or remote scripting or AJAX enabled, whatever way you like to call it. For more information check out http://msdn.microsoft.com/msdnmag/issues/04/08/cuttingedge/
TreeView - You always wanted, now it is here
While a TreeView is such a popular control required, it was always missing in the earlier versions of ASP.NET. Users have to resort to using the less extensible "IE Webcontrols" or run behind third party solutions. ASP.NET 2.0 comes with a built-in TreeView control which is tested and works fine across Firefox, etc., and also provides properties and methods including On Demand (again AJAX Feature) loading of child nodes. Check my own blog's ASP.NET 2.0 Category articles for a few posts on TreeView
MultiView - Finally there is a Tab Control
As much as TreeView is important, a Tabbed Control was always required to show different portions of page in the same page. The MultiView provides you a tabbed interface for showing different sections of your page within the same page, on demand. It is a cool utility to provide Tabbed interface to your pages.
Whenever you Cache enable your page, all portions of your page become more or less static until the Cache gets invalidated. However, if you have a little nifty section of your page (Cricket Score? eh ? ) that needs to always retrieve fresh data, dont blame Cache and remove it from the whole page. Use the substitution control which can help you in making a portion of your page dynamic using the method you provide to use for constant update.
PreviousPage - How I wonder what was there (in the previous page)
Dealing with web applications is such a nuisance considering that it is state less and we need to preserve values across postback. Session has been beaten to death though its still a good way. But what if I want to retrieve the TextBox value of the previous page, use the Page.PreviousPage property to retrieve the control's reference and get the value of the TextBox. Of course this works only if you were in the previous page before coming to this page, but that can be checked and validated.
Default Button - Hit Enter Key and get what you want it to do
Enter Key has always been challenging in form submission and if you have multiple buttons in your page, you never know which one is firing when user hits enter. I have seen sites till date which allow me to enter registration information and when I press "Enter" to complete take me to the "Search" Page since it is the first button on the top of the page. With ASP.NET 2.0, the Default Button is a property that can be set at the Form level / panel level to specify which button should be fired when the user hits the "Enter" Key and accordingly act. Its a cool utility which provides complete control of where you want to fire an event upon user hitting the "Enter" button.
You are already writing a Mobile Applicaiton
In ASP.NET 1.x versions you had to use the MMIT (Microsoft Mobile Internet Toolkit) for writing pages that can be rendered on Mobile Devices. However, with ASP.NET 2.0 your pages that run on the browser, automatically run on mobile devices since the rendering capabilities and the user agent is automatically determined before the page is rendered. So, your ASP.NET 2.0 Page can also be viewed over devices, without additional effort from you.
I think I tried to provide 10 things you might not know about ASP.NET 2.0 and that is the reason, I have avoided mentioning things like GridView, MasterPages, Themes etc., which have been dealt with for a long time now.
Many of these are little things which can help with your web development and if you have issues with these, we would like to hear your development experiences, so please post them in your comments.
You might receive the error 'Sys' is undefined when running ASP.NET AJAX Web pages or trying to AJAX enable your exisitng Web Applicaitons.
This error occurs specifically when you try upgrading your existing ASP.NET 2.0 Applications to AJAX by using the ASP.NET AJAX controls like UpdatePanel, etc., The common cause for this error is that you havent updated the Web.Config file of the application to enable the runtime understand ASP.NET AJAX. Let me explain a little more.
To resolve the issue, I am providing herebelow the steps:-
Open the Web.Config file and start adding the following settings to the same:- (Forewarning: Modifying Web.Config incorrectly makes your site inaccessible and I would suggest you take a back up of your existing web.config file before making the following changes. This article is intended for people with prior experience in dealing with web.config file, settings etc., and if you arent very convenient working with the Web.Config file, make your administrator or other experienced developers make these changes)
1. Below the <configuration> tag, add the following settings:-
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere"/>
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
What we have done in this step is registering the System.Web.Extensions namespace, the assembly and its various handlers that are useful in handling AJAX for your ASP.NET 2.0 Application.
2. Then, below the <system.web> add the following settings:-
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
In this step, we registered the tagprefix of ASP for the ASP.NET AJAX Server controls like UpdatePanel so that we can use the same <asp: prefix while using the same in your pages. Ex.- <asp:UpdatePanel>
3. Then find the <compilation debug="false" /> and you need to replace this line with the following settings:-
<add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
This step enables compilation for your website and adds the reference assembly for System.Web.Extensions.
4. Then below the compilation settings (above step), add the following:-
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
5. Then, after the </system.web> end tag, add the following system.web.extensions settings:-
<!-- Uncomment this line to customize maxJsonLength and add a custom converter -->
<add name="ConvertMe" type="Acme.SubAcme.ConvertMeTypeConverter"/>
<!-- Uncomment this line to enable the authentication service. Include requireSSL="true" if appropriate. -->
<authenticationService enabled="true" requireSSL = "true|false"/>
<!-- Uncomment these lines to enable the profile service. To allow profile properties to be retrieved
and modified in ASP.NET AJAX applications, you need to add each property name to the readAccessProperties and
writeAccessProperties attributes. -->
<scriptResourceHandler enableCompression="true" enableCaching="true" />
In this step, we have additional steps where we can play with JSON Serialization settings and enabling some of the Application Services like AuthenticationService, ProfileService etc.,
6. Thereafter, add the following system.webServer settings:-
<add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
The above steps registers the ScriptHandlerFactory for Webservices and the AXD that needs to handle the requests.
Once you have added the above steps to your web.config file, you would be able to add ScriptManager, UpdatePanel and other ASP.NET AJAX Controls and would be able to run the page. This should solve the 'Sys' is undefined error message.
These settings are not required if you are creating a "File - New - AJAX Enabled Website" using Visual Studio 2005 since all the above settings are added automatically to your web.config file.
Similarly, with Visual Studio "Orcas" any ASP.NET Website created will automatically have these settings as a part of the web.config file enabling you to directly use the ASP.NET AJAX Server side controls as well as the client scripts.
This error may also occur, if you are running beta versions of ASP.NET AJAX such as RC1, and earlier CTP versions. I would strongly suggest you to upgrade to the released version of ASP.NET AJAX which can be downloaded from http://ajax.asp.net and update / modify your web.config files accordingly.
Finally, this error occurs due to the fact that 'Sys' is the root namespace for Microsoft AJAX Library and the web.config settings specify the Handlers / Modules and the System.Web.Extensions DLL references so that the runtime can understand and render accordingly.
If you are still facing the error after checking the above, write back in comments so that I can help you with the same.
My second session at Tech Mela which was also the second session on the first day of Web Platform track was a Deep Dive on ASP.NET AJAX. The topic I did as Deep Dive was on Update Panel internals. Update Panel is the most popular ASP.NET AJAX Server control used widely for AJAX enabling your ASP.NET Pages. A better understanding of the same would help in using it in a better way. So, here I am providing the contents and the specifics discussed during my session.
UpdatePanel is one of the important ASP.NET AJAX Extensions server side controls used when you are developing AJAX enabled ASP.NET Websites. ( For some basic level articles, samples on UpdatePanel refer to my earlier posts in this blog on the same http://geekswithblogs.net/ranganh/category/6604.aspx )
While it is the simplest way you can AJAXify your page, it also accounts to certain performance issues when used in an improper way. Before we get into using the UpdatePanel effectively, let us find out how the UpdatePanel works internally.
First step is dissecting the UpdatePanel. When you declare an UpdatePanel in your ASP.NET Page, the HTML markup that is generated is as follows:- (For sample purposes, I put a simple Submit button inside the updatepanel)
<input type="submit" name="button1" value="Refresh" id="button1" />
So, the rendered HTML is actually a Div with the ID of the UpdatePanel. However, the interesting portion of code which does the magic is as follows (as rendered in the HTML)
Sys.WebForms.PageRequestManager.getInstance()._updateControls(['tUpdatePanel1'], , , 90);
Note the above lines. "Sys" is the root namespace of Microsoft AJAX Library and it is comparable to "System" which is the root namespace for .NET Classes. The first line above calls the initialize method of the PageRequestManager class passing the two parameters 'ScriptManager1' which is the ID of the Script Manager control and the ID of the Form element of the page.
The UpdatePanel control doesnt really do any magic here. It is the ScriptManager control and the PageRequestManager class which is installed as a part of the ASP.NET AJAX installation, which does the partial page rendering mechanism.
Note that, even if you dont add any UpdatePanel or any other control to your webform, the moment you add a ScriptManager control to your page, the mark up generated has the above 2 lines. The only difference would be the 'tUpdatePanel1' which in the case of a page without any UpdatePanel, would be a blank array like the rest of them in the list (2nd line above).
So, what happens if I add multiple UpdatePanels to the page? the 2nd line is changed as follows:-
Sys.WebForms.PageRequestManager.getInstance()._updateControls(['tUpdatePanel1','tUpdatePanel2','tUpdatePanel3'], , , 90);
So it keeps appending the UpdatePanel IDs to the first array. The moment you add a trigger to the UpdatePanels, the second array gets the ID of the trigger controls appended to it.
Example: I modified the first UpdatePanel declaration as follows:-
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="conditional">
<asp:AsyncPostBackTrigger ControlID="Button4" EventName="Click" />
The resulting HTML generated is modified as follows:-
Sys.WebForms.PageRequestManager.getInstance()._updateControls(['tUpdatePanel1','tUpdatePanel2','tUpdatePanel3'], ['Button4'], , 90);
If you use the same trigger i.e. Button4 for all the UpdatePanels, the above line is unaltered. However, when you use multiple buttons (triggers) i.e. Button5, Button6 for the different UpdatePanels, the items get appended to the list i.e. 'Button4', 'Button5', Button6' etc.,
Ok, enough of HTML exploration. What next? Give me a break.. Will continue in Part 2 of this article.
Last month, I did a Virtual Classroom series on ASP.NET AJAX. It was a five day intense AJAX Webcast series with a lot of interaction by means of polls / questions from the attendees.
The first day was an overview of different tenets of ASP.NET AJAX and the rest of the four days went into each one of the following topics in detail:-
Microsoft AJAX Library
ASP.NET AJAX Extensions
AJAX Control Toolkit
I thank all of those who took their time out and attended the same and I hope you found it beneficial. I did manage to respond to many of your technical queries and for your queries regarding Certificates and Prizes, please check with the http://www.microsoft.com/india/virtualclassrooms page shortly when this information would be put up.
If you were unable to catch up with the webcasts, you can view the recordings for free from the Ondemand Page available at http://www.microsoft.com/india/virtualclassrooms/ondemand3.aspx