Accessing Embedded Resources using GetManifestResourceStream
How do you access resource files (bmp, mp3, etc) that are compiled into your Windows Forms executable? After googling the subject, the Assembly object's GetManifestResourceStream method seemed to be the solution. MSDN's entry on this subject makes it seem relatively simple. However, it took me over an hour to get it to work in my latest project. There are two things you must do in other to access an executable's resources:
1.You must know the exact name of resource (mynamespace.resource.resourcename).
2.You must embed the resource into your executable.
Accessing the resources means that you must have access to the executable's Assembly object.
Example
Assembly resourceAssembly = Assembly.GetAssembly(typeof(Program));
string[] names=resourceAssembly.GetManifestResourceNames();
foreach (string str in names)
{
Console.WriteLine(str);
}
using (StreamReader stream = new StreamReader(resourceAssembly.GetManifestResourceStream("ConsoleApplication2.NewFolder1.Embed.xml")))
{
string str=stream.ReadToEnd();
}
How to enable remote debugging when you don't have Visual Studio on Servers
Posted by milap shah on Thursday, May 14, 2009Remote Debugging is a great feature to use, especially when you work with virtual machines. It allows you to develop and debug locally but have the code running on another machine, virtual or physical. Microsoft SharePoint can't be installed on a Windows Vista or XP workstation, but needs to be installed on Windows Server 2003 or 2008, so the general recommendations has been for developers to have either Windows Server as their main OS or have a virtual machine with Windows Server. None of these work that well; either you have problems debugging your components and you have to rely on traces or message boxes or you have to have a virtual machine with a full development environment, which will not resemble a production machine.
So, Remote Debugging, is my primary way when working with SharePoint development. It allows you to have a smaller virtual machine, and it will allow you to develop in your main OS. But, Remote Debugging has been quite problematic to set up and configure, so here is a guide that you can follow to get it work in a few minutes.
This guide uses Microsoft Visual Studio 2008 and Windows Vista with UAC on the client and a Windows Server 2003 with WSS 3.0 running in a Virtual PC on the client.
Prepare your remote host
First of all you need to prepare your remote host for accepting incoming debugging requests, this is done by running the Visual Studio Remote Debugging Monitor on the remote machine, which is found under C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\Remote Debugger\. Copy that folder to your remote host and place a shortcut to the msvsmon.exe on the desktop, so you have fast access to it whenever you need to debug.
The Remote Debugging Monitor is the one accepting your debug calls and the talking back to Visual Studio on your client, so to get these things to work you have to start the client as the user running Visual Studio (or have administrative permissions on the client). You can either log in to the remote host using that user or, as I prefer, right-click on the msvsmon.exe and choose Run As... Make sure that the user you are using to run the monitor with is member of the local Administrators group.
Now the Remote Debugging Monitor has started to waiting for new debugging connections. The debugging server was named with the username that is running the application and the server name, separated with an @-character. You can rename it using Tools->Options.
Prepare your client
Now it's time to prepare your client. First of all you have to run the Visual Studio 2008 Remote Debugger Configuration Wizard, which will open up the correct ports in your firewall. You will find the wizard under the Visual Studio Tools in your start menu. The wizard also allows you to run the Remote Debugger as a service on the machine which the wizard is run on, skip this step for this guide. When the wizard asks you for how you would like to configure your firewall, choose the Allow only computers on the local network... option and the finish the wizard.
Start Debugging
Now it's time to start Visual Studio 2008 and load up your solution and hook up the debugger to the remote machine. Prior to this you need to deploy the application to be debugged on the remote machine, including the .pdb files.
In Visual Studio choose Debug->Attach to process. In the Qualifier you have to enter the name that was given to the Remote Debugger Monitor and hit Enter, then all you need to do is attach to the process you would like to debug and set some break points!
That wasn't to hard?
Problems
Here are some problems that I have stumbled upon when trying to get these things to work.
Unable to connect to the Microsoft Visual Studio Remote Debugging Monitor named 'XXX. The Visual Studio Remote Debugger on the target computer cannot connect back to this computer. Authentication failed. Please see Help for assistance.
This one is due to the fact that the user running the debugging monitor are not allowed to access the client machine, make sure that the user running the monitor is either the same user running Visual Studio or the member of the Administrators group on your client.
You only see a few processes in the Attach to Process dialog.
First of all make sure you have checked the Show processes from all users check box, then make sure that the user running the monitor has access to the process on the machine, that is you have to make the user member of the local Administrators group. After adding the account to the Administrators group you have to restart the monitor.
Unable to connect to the Microsoft Visual Studio Remote Debugging Monitor named 'ibvsretail'. Logon Failure: The target account name is incorrect.
This one is pretty uncommon, but still I have had it. Somehow the server account in Active Directory had gone wrong so I hade to remove the machine from the domain and add it back.
For asp.net Server Controls if you want to access code behind variable in aspx pages. There are 3 things to remember:
1. Scope of the variable has to be protected or Public
2. The variable can be accessed only using DataBinding Syntax like below.
<asp:TextBox ID="TextBox1" runat="server" Text='<%# DateTime.Now.ToString()%>'></asp:TextBox>
3.You have to Call Page.DataBind() or TextBox1.DataBind() method in the Page_Load event or any other event before Page_Render event's base.Render(writer) method call.
For HTML controls you could just use the traditional syntax like below.
<input type='text' value='<%=DateTime.Now.ToString()%>' />
There are two kind of Serialization that you could perform on the object Xml and Binary.
Samples are below.
Suppose We have Class Animal.
[Serializable]
public class Animal
{
public Animal()
{
}
[NonSerialized]//field which doesn't required to be serialized and deserialized
public String animalName;
public String foodTypeCategory;
public Boolean isDomesticed;
}
Xml Serializer doesn't need class to be marked as Serializable while Binary Serialization does.
//Xml Serialization
class Program
{
static void Main(string[] args)
{
Animal cow = new Animal();
cow.animalName = "Cow";
cow.foodTypeCategory = "Any";
//Stream stream = File.Open("c:\\abc.xml", FileMode.Create);
MemoryStream stream = new MemoryStream();
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Animal));
serializer.Serialize(stream, cow);
byte[] array = stream.GetBuffer();
stream.Close();
MemoryStream stream1 = new MemoryStream(array);
Animal obj1 = (Animal)serializer.Deserialize(stream1);
}
}
For Binary Serialization the only line which changes in the above code is XmlSerializer object creation line which will be replaced with
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serializer = new BinaryFormatter();
Also If some time you want to Control the Serialization And Deserialization of your class then you could Implement ISerializable interface and override following methods for Animal class as an example.
public Animal(SerializationInfo info, StreamingContext ctxt)
{
animalName=(String)info.GetValue("animalName",typeof(string));
foodTypeCategory = (String)info.GetValue("foodTypeCategory", typeof(string));
isDomesticed = (Boolean)info.GetValue("isDomesticed", typeof(bool));
}
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
info.AddValue("animalName", animalName);
info.AddValue("foodTypeCategory", foodTypeCategory);
info.AddValue("isDomesticed", isDomesticed);
}
Also If you want to convert string to byte[] and byte[] to String you could use following functions.
private String UTF8ByteArrayToString ( Byte[ ] characters )
{
UTF8Encoding encoding = new UTF8Encoding ( );
String constructedString = encoding.GetString ( characters );
return ( constructedString );
}
///
/// Converts the String to UTF8 Byte array and is used in De serialization
///
///
///
private Byte[ ] StringToUTF8ByteArray ( String pXmlString )
{
UTF8Encoding encoding = new UTF8Encoding ( );
Byte[ ] byteArray = encoding.GetBytes ( pXmlString );
return byteArray;
}
Maximum timeout value: 10 min(default). If your application requires different maxTimeout value then you could configure it in machine.config file which would be applicable to all the applications. maxTimeout can only be specified in machine.config file and it will be applicable to all the apps.
Sample:
<configuration>
<system.transactions>
<machinesettings maxtimeout="00:02:00">
</system.transactions>
</configuration>
Configurable timeout value: 1 min(default). If you want specific timeout value other than 1 minute you could set it in either app.config(application specific) and/or machine.config(machine wide setting) or in code as well.
Sample:
<system.transactions>
<defaultsettings timeout="00:00:59">
</system.transactions>
Note: If the specified defaultSettings timeout value is greater than maxTimeout then maxTimeout value will take precedence.
This is an excellent Post on Multithreading
Introduction
Understanding Page lifecycle is very crucial in order to develop ASP.NET applications. Most beginners tend to get confused while dealing with dynamic controls and face problems like losing values, state etc on postbacks. Since HTTP is stateless, the nature of web programming is inherently different from windows application development, and the Page lifecycle is one of the primary building blocks while learning ASP.NET. The sequence of events, especially while working with MasterPages in ASP.NET 2.0, has become slightly more complex and this article is aims to shed some light on these events by explaining the order and importance of each event.
Background
Whenever the user requests a particular .aspx page in an application, a lot of interesting things happen on the web server where the application is hosted. Understanding this sequence of events will help us to program and respond to events properly and also clear any confusion which generally arises due to the stateless nature of web programming.
Basics: The New Compilation Model and the Partial Classes
Each web form in an ASP.NET application derives directly or indirectly from a System.Web.UI.Page class. A web form has two components: a code behind file (WebForm.aspx.cs) which contains the code for the events and other methods related to a Page, and the designer ASPX file, which contains HTML control declarations and events (in the Visual Studio 2005 Web Application project model, we have a designer class named WebForm.aspx.designer.cs).
In ASP.NET 2.0, we do not need to define the control variables as well as there event handlers in the code behind, thanks to Partial classes. In ASP.NET 1.x, all this code was auto generated and placed in the code behind file under InitializeComponent() section. But in version 2.0, the runtime will create a partial class dynamically from the ASPX page containing all this info and merge it with the code behind partial class. This will help in making the actual code behind class a lot cleaner and more manageable.
Also, this would eliminate the name change related issues which were common in VS 2003 (if we change any control's ID, it had to be changed everywhere and VS used to modify the code many times). All control related events are defined in the ASPX markup code. So having a single place for controls names and event handlers is cleaner and flexible, whereas the previous VS 2003 model was more "brittle".
Real Thing: The Page life cycle
It is very important to know that for each request, the Page class is instantiated everytime from “scratch”. Which means that any values or whatever state it had previously will get lost unless we use one of the various state maintainance mechanisms provided by ASP.NET like Application, Session, Cache variables or Cookies.
Side Note: View state in ASP.NET 2.0 has changed and now comprises of two parts: Control State and View state. Refer this article for details:
http://msdn2.microsoft.com/en-us/library/1whwt1k7(VS.80).aspx
Below is the sequence of events which fire up sequentially with explanation on the relative importance with respect to web programming in code behind:
Important Note: All events except the Init() and Unload() are fired from outermost to the innermost control. For e.g., a user control’s init event would fire before the Page_Init() event of its parent Page class.
1. PreInit()
In this Page level event, all controls created during design time are initialized with their default values. For e.g., if you have a TextBox control with Text property = “Hello”, it would be set by now. We can create dynamic controls here.
This event occurs only for the Page class and UserControls/MasterPages do not have this method to override. Sample code where you can override this method and add your custom code:
protected override void OnPreInit(EventArgs e)
{
//custom code
base.OnPreInit(e);
}
Note that PreInit() is the only event where we can set themes programmatically.
Special Case with MasterPages
It is important to note that Master Page is treated like a control in the Content Pages.So if a Page has a Master Page associated with it, then the controls on the page will not be initialized and would be null in this stage. Only after the Init() event starts, you can access these controls directly from the page class. Why?
The reason being that all controls placed in the Content Page are within a ContentPlaceholder which is a child control of a MasterPage. Now Master Page is merged and treated like a control in the Content Pages. As I mentioned earlier, all events except the Init() and Unload() are fired from outermost to the innermost control. So PreInit() in the Page is the first event to fire but User Controls or MasterPage (which is itself a Usercontrol) do not have any PreInit event . Therefore in the Page_PreInit() method, neither the MasterPage nor any user control has been initialized and only the controls inside the Page class are set to their default values. Only after the Page_PreInit() event the Init() events of other controls fire up.
See the diagram below showing control hierarchy after the Page_Init() event:
2. OnInit()
In this event, we can read the controls properties (set at design time). We cannot read control values changed by the user because that changed value will get loaded after LoadPostData() event fires. But we can access control values from the forms POST data as:
string selectedValue = Request.Form[controlID].ToString();
3. LoadViewState
This will only fire if the Page has posted back (IsPostBack == true). Here the runtime de-serializes the view state data from the hidden form element and loads all controls who have view state enabled.
4. LoadPostBackData
Again, this method will only fire if the Page has posted back.In this event the controls which implement IPostBackDataHandler interface gets loaded by the values from the HTTP POST data. Note that a textbox control does not gets its value from the view state but from the post data in the form in this event. So even if you disable view state for a particular control, it can get its value from the HTTP POST data if it implements IPostBackDataHandler interface.
Also, an important point to note is that if we have a DropDownList control and we have dynamically added some items to it, the runtime cannot load those values unless the view state is enabled (even if the control derives from IPostBackDataHandler). The reason being that HTTP Post data has only one value per control, and the entire value collection is not maintained in the PostData but in view state.
5. Page_Load
This is the most popular method and the first one for all beginner developers to put their code. Beginners may also think that this is the first method which fires for a Page class. This can lead to a lot of confusion which makes understanding the Page lifecycle all the more important.
Note: If the page has any user control, then it's Load method will fire after the Page class's Load method. The reason as explained earlier is the fact that all method except the Init() are fired from the outermost control to the innermost. So after Page_Load(), load methods of all other controls are fired recursively.
6. Control Event Handlers
These are basically event handlers (like Button1_Click()) which are defined for controls in the ASPX markup. Another source of confusion arises when the developer thinks that an event handler like Button_Click() should fire independently (like in windows apps) as soon as he clicks a Button on the web form, forgetting that Page_Load will fire first before any event handlers.
7. PreRender
This event is again recursively fired for each child controls in the Page. If we want to make any changes to control values, this is the last event we have
to peform the same.
8. SaveViewState
Here, the ViewState of the controls gets saved in the form's hidden control.
9. Render
In this method all controls are rendered recursively (i.e. Render method of each control is called).
10. Unload
Here you can have the page and controls perform clean-up operations. This event has no relevance besides clean up operations because the Page has already rendered.
Dynamic Controls
Now we have seen the important events in the Page lifecycle, let's focus on how to create and maintain state of dynamically generated controls. Many times we need to generate controls dynamically for specific business use cases. For example, I was managing a famous hotel reservation website project and one of my team members was facing an issue in handling the Reservation screen. There was a TextBox where the user enters the number ofrooms, and based on that value, dynamic usercontrols having a room's detailed info were created at runtime.
The developer complained that although he was able to generate user controls as runtime in a for loop, but was unable to save their state. When I looked into the code, I noticed that the code to generate controls was written in a Button's Click event handler. Now as we dicussed above, event handlers like Button_Click() fire much later than LoadViewState() and LoadPostData(), where the control values get loaded from the view state and form's Post data.
So unless he recreates the controls in the Page_Init() or Pre_Init() methods (which occur before LoadViewState and LoadPostData), the control values modified by the user won't get reloaded next time.
Now, when he put the code in the Page_Init() event, he was unable to get the number of rooms entered by the user in the TextBox (which was a static control). The reason being that in Page_Init(), control values are initilized to their design time default values, and do not reflect the user entered values unless they are loaded from the POST data or the view state, a process which occurs later.
So the only way to access the user entered value in the control is to get the value from the form's POST data. Here is the code:
protected override void OnInit(EventArgs e)
{
//get value of the TextBox from HTTP POST data
string selectedValue ;
if(Request.Form["txtNoOfRooms"] != null) selectedValue = Request.Form["txtNoOfRooms"].ToString();
//code to create controls dynamically...
...............
base.OnInit(e);
}
Note: Thanks to Mike Banavige of ASP.NET forums, I added this section. If you create a dynamic control in the Page_Load event, and add it to a PlaceHolder or Panel (with view state turned on), then this dynamic control will maintain its state even though it was not created in the Page_Init(). Why?
The reason is the fact that once a control is added to the control tree of the page, TrackViewState() method is responsible for tracking the state. This method gets fired automatically whenever the control is added to the control tree. Due to this reason, any modifications to the control (like adding items etc) should be done *only after* the dynamic control has been added to the control tree of the Page class, else the state would be lost. See the code below:protected void Page_Load(object sender, EventArgs e)
{
//create a dynamic dropdown
DropDownList d = new DropDownList();
PlaceHolder1.Controls.Add(d); // TrackViewState() gets fired for our dropdown, so state is maintained
if (!IsPostBack)
{
d.Items.Add("test1");
d.Items.Add("test2");
}
}This will not work:protected void Page_Load(object sender, EventArgs e){//create a dynamic dropdownDropDownList d = new DropDownList();if (!IsPostBack){d.Items.Add("test1");d.Items.Add("test2");}PlaceHolder1.Controls.Add(d); //"test1" and "test2" values are lost}
Summary
I have tried to explain relevant events in the Page lifecycle and their importance with some gotchas. I will keep updating this article with more tips and tricks, besides readers are welcome to point out mistakes and suggest corrections and give feedback!
An important thing to remember here is that the entire lifecycle is repeated on every request. The Page class gets re-instantiated and after serving the request gets unloaded. Once we are clear with the sequence of the events, we can structure our code well to suit different use case requirements.
