Blog Home  Home Feed your aggregator (RSS 2.0)  
kevin Mocha - Saturday, March 06, 2010
Bookmarks collected from web.
 
 Saturday, March 06, 2010

Maintaining State

If a unique response per client is desired, something in the HTTP request itself must be unique.

Once a method of state management has been established, you need only to authenticate the user once. Because state management provides a way to identify a Web client, user identification simply requires that you remember which user is associated with which client upon authentication.

When I speak of maintaining state, I am only speaking of client identification, which is accomplished by associating multiple HTTP requests.

Maintaining session, on the other hand, requires two related tasks:

  • Identifying the client (state management)

  • Retaining information about the client

Although cookies are most often described in conversation as if they are entities (for example, "a Web server sends you a cookie"), they are much easier to understand at a functional level if you consider them an extension of the HTTP protocol, which is actually more correct. Cookies can be defined as the addition of two HTTP headers:

  • Set-Cookie response header

  • Cookie request header

image

    A common question seen on mailing lists and discussion forums for Web developers is how to test whether the client is accepting cookies, and many people do not understand the answer. As is evident in Figure 11.3, it is impossible to determine whether the client accepted the cookie until the second request is sent (step 3 in the figure). If the cookie is included in the second request, the client accepted it. If not, the client rejected it.

Some developers choose to force the issue of determining whether the client accepts cookies by redirecting the client to a second URL upon entrance.

Cookies have become a source of privacy concern in recent years. As with most technologies in the computer industry, this reputation has been earned by the misuse of the technology more than the technology itself.

Whether using files or a database to store the session information, there are three basic elements you will want to store for each session's record:

  • Unique identifier

  • Timestamp of last access

  • Client data

image

 

Improve the performance

Caching can refer to many concepts. The general meaning of cache is to store a copy of something to prevent the necessity of retrieving it again. When speaking of Web development, there are three main types of caching:

  • Caching on the server— Storing a complete or partially generated resource on the server to keep from having to regenerate it.

  • Caching on the client— Storing a resource on the client to keep from having to receive the entire resource again.

  • Proxy caching— Storing a resource on a proxy to allow direct replies to an HTTP request rather than having to receive the entire resource from the origin server again.

Although there are many side advantages to caching, there are three core benefits:

  • Improve response time from a user perspective— This is what most Web developers focus on, the user experience.

  • Lessen network load— Many Web developers overlook this metric because bandwidth is often viewed as an expendable resource, where more can be purchased as needed.

  • Lessen server load— This metric is more difficult to overlook, as it directly impacts the user experience in terms of performance and reliability (stressed servers fail more often).

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Saturday, March 06, 2010 8:56:19 PM UTC  #    Comments [0]    |   |  Trackback

It is important to remember that an HTTP response completes the HTTP transaction. Many people new to Web development have a difficult time distinguishing between server-side code (code that executes on the server) and client-side code (code that executes on the client). Scripting languages such as PHP, ColdFusion, and JSP are executed on the server, and their output is included in the HTTP response. In fact, their output is the content of the HTTP response, and most modern Web scripting languages also allow for some manipulation of the HTTP as well, such as altering or adding headers, changing status codes, and so on. Once the Web client receives the HTTP response, the transaction is complete. The Web client will then render the page, execute client-side scripts such as JavaScript, load images (by issuing separate GET requests), and so on.

 

With HTTP/1.1, persistent connections are the default behavior. This means that the Web server will not close the connection after sending the HTTP response unless the client intends to close the connection after receiving it. In this case, the client will include the following header in the HTTP request:

Connection: close 

Alternatively, the server can close the connection upon sending the HTTP response, although it should be polite and include the same header as shown previously so that the Web client expects this action.

 

An HTTP response is broken into the following three logical pieces:

  • Status line

  • HTTP headers

  • Content

An example status line is as follows:

HTTP/1.1 200 OK 

The status line contains three elements:

  • The version of HTTP being used, in the format HTTP/x.x

  • The status code

  • A short description of the status code

There are three types of HTTP headers allowed in a response:

  • General headers

  • Response headers

  • Entity headers

 

Status codes are grouped into the following ranges:

  • Informational (100-199)

  • Successful (200-299)

  • Redirection (300-399)

  • Client error (400-499)

  • Server error (500-599)

 

  • 100 Continue
  • 101 Switching Protocols
  • 200 OK
  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • 500 Internal Server Error
  • 502 Bad Gateway
  • 503 Service Unavailable

Content-Disposition, combined with a proper Content-Type header, provides the developer absolute control over the interpretation of the resource's media type.

Saturday, March 06, 2010 5:51:07 AM UTC  #    Comments [0]    |   |  Trackback
 Friday, March 05, 2010

 

image image image

Server: new a socket –> bind to listen port –> Accept a connection –> send/receive –>close
Client: new a socket –> connect –>send/receive –> close

http://myname:mypass@httphandbook.org:80/mydir/myfile.html?myvar=myvalue#myfrag

image

HTTP is often referred to as a stateless protocol. Although this is accurate, it does little to explain the nature of the Web. All this means, however, is that each transaction is atomic, and there is nothing required by HTTP that associates one request with another. A transaction refers to a single HTTP request and the corresponding HTTP response.

When I speak of a connection in HTTP, I refer to a TCP connection.

A single connection can support multiple HTTP transactions. In many cases, multiple HTTP transactions are required to properly render a URL in a Web browser due to images and other associated content.

image

Get and Post

GET and POST basically allow information to be sent back to the webserver from a browser (or other HTTP client for that matter).

Imagine that you have a form on a HTML page and clicking the "submit" button sends the data in the form back to the server, as "name=value" pairs.

Choosing GET as the "method" will append all of the data to the URL and it will show up in the URL bar of your browser. The amount of information you can send back using a GET is restricted as URLs can only be 1024 characters.

A POST on the other hand will (typically) send the information through a socket back to the webserver and it won't show up in the URL bar. You can send much more information to the server this way - and it's not restricted to textual data either. It is possible to send files and even binary data such as serialized Java objects!

A PUT allows you to "put" (upload) a resource (file) on to a webserver so that it be found under a specified URI. DELETE allows you to delete a resource (file). These are both additions to HTTP/1.1 and are not usually used. HEAD returns just the HTTP headers for a resource. TRACE and OPTIONS are also HTTP/1.1 additions and also rarely used.

 

Although client-side data validation can add to user convenience by avoiding unnecessary HTTP transactions, you should never depend on this technique to ensure the data is valid.

GET /search?hl=en&q=HTTP&btnG=Google+Search HTTP/1.1 
Host: www.google.com 
User-Agent: Mozilla/5.0 Galeon/1.2.0 (X11; Linux i686; U;) Gecko/20020326 
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9, 
        text/plain;q=0.8, video/x-mng,image/png,image/jpeg,image/gif;q=0.2, 
        text/css,*/*;q=0.1 
Accept-Language: en 
Accept-Encoding: gzip, deflate, compress;q=0.9 
Accept-Charset: ISO-8859-1, utf-8;q=0.66, *;q=0.66 
Keep-Alive: 300 
Connection: keep-alive 

Broken down, the request line is

 

An HTTP request, which is the message sent from a Web client to a Web server, is comprised of three basic elements:

  • Request line

  • HTTP headers

  • Content

The first line of an HTTP request is always the request line. The request line specifies the request method, the location of the resource, and the version of HTTP being used. These three elements are delimited by spaces. For example:

GET / HTTP/1.1 

This example specifies the GET request method, the resource located at / (document root), and HTTP/1.1 as the version of protocol used.

 

The second section of an HTTP request is the headers. HTTP headers include supporting information that can help to explain the Web client's request more clearly. There are three types of HTTP headers that can appear in a request:

  • General headers

  • Request headers

  • Entity headers

There is no requirement pertaining to the order of the headers. Also, because entity headers specify information about the content, they are rarely present in HTTP requests.

 

In general, it is fairly easy to discern which category a header belongs to. Request headers specifically relate to something unique to an HTTP request, such as the User-Agent header which identifies the client software being used. General headers are common headers that can (at least theoretically) be used in either an HTTP request or an HTTP response. Entity headers relay information about the content itself (the entity). As this request has no content, it also lacks entity headers.

 

There are eight request methods in HTTP/1.1: GET, POST, PUT, DELETE, HEAD, TRACE, OPTIONS, and CONNECT. HTTP/1.0 specifies three methods (GET, HEAD, and POST), although four others are implemented by some servers and clients claiming to be HTTP/1.0. The support for these four other methods (PUT, DELETE, LINK, and UNLINK) is inconsistent and mostly undefined, although they are each briefly referenced in Appendix D of RFC 1945, the HTTP/1.0 specification.

 

A GET request is basically a request to receive the content located at a specific URL. Obtaining a URL using the GET method allows users to bookmark the URL, create a link to the URL, email the URL to a friend, and the like. There is a limited amount of data that can be sent from the Web client using get, and this limit is very inconsistently implemented.

 

The POST method is commonly supported by browsers as a method of submitting form data.
As with the query string of a URL, the data in a POST consists of name/value pairs separated by the & character. Special characters are URL encoded, and the Content-Type header references this fact.

 

For many forms, the POST method is preferable.

 

The PUT method is not nearly as common as GET or POST. However, it is useful in certain situations because it allows the Web client to send content that will be stored on the Web server.
It should be noted that the PUT method is very rarely implemented in Web clients. A common misconception is that the PUT method is required for uploading files. However, this capability is actually an enhancement to the POST method as identified in RFC 1867, "Form-based File Upload in HTML".

 

HEAD is a very useful request method for people who are interested in finding out more information about the way a certain transaction behaves. The HEAD method is supposed to behave exactly like GET, except that the content is not present. Thus, HEAD is like a normal GET request with all of the HTML stripped away.

 

TRACE is another diagnostic request method. This method allows the client to gain more perspective into any intermediary proxies that lie between the client and the server. As each proxy forwards the TRACE request on route to the destination Web server, it will add itself to the Via header, with the first proxy being responsible for adding the Via header. When the response is given, the content is actually the final request including the Via header.

 

Sometimes it is helpful to simply identify the capabilities of the Web server you want to interact with prior to actually making a request. For this purpose, HTTP provides the OPTIONS request method.

 

The CONNECT request method is reserved explicitly for use by intermediary servers to create a tunnel to the destination server. The intermediary, not the HTTP client, issues the CONNECT request to the destination server.
The most common use of the CONNECT method is by a Web client that must use a proxy to request a secure resource using SSL (Secure Sockets Layer) or TLS (Transport Layer Security). The client will tunnel the request through the proxy so that the proxy will simply route the HTTP messages to and from the Web server without trying to examine or interpret them.

 

Accept Header

Authorization Header
Once the browser has successfully authenticated with a Web server in this way, it will appear to a user as if all further requests do not require reauthentication. However, due to the stateless nature of the Web, every request must include the Authorization header, otherwise the server will respond with a 401 Unauthorized response. The convenient behavior of most modern Web browsers involves the browser storing the access credentials and sending the Authorization header with all HTTP requests for a URL within a domain previously discovered to be protected. Because this utilizes the browser's memory, this convenience lasts as long as the browser (at least one instance of the browser) remains active, and the user will be unaware that this authentication takes place in subsequent requests. This can be a very important factor when debugging HTTP authentication, because if you receive a 401 Unauthorized response without being prompted for a username and password, this suggests that the browser is using incorrect credentials in the Authorization header. Restarting the browser will resolve this situation.

Friday, March 05, 2010 9:58:27 PM UTC  #    Comments [0]    |  Trackback

Form 2.0 data binding

Binding nameBinding = new Binding("Text", this.raceCarDriver, "Name", true); 
this.nameTextBox.DataBindings.Add(nameBinding);
or 
this.nameTextBox.DataBindings.Add( "Text", this.raceCarDriver, "Name");

The minimum implementation that is considered a list data source by the Windows Forms binding engine is a class that implements the IList interface (from System.Collections).

this.BindingManager.Position = 0; 
RefreshItems();

this.raceCarDriversListBox.DataSource = this.raceCarDrivers;
this.raceCarDriversListBox.DisplayMember = "Name";

void addButton_Click(object sender, EventArgs e) {
  // Add item to list data source directly
  RaceCarDriver raceCarDriver = new RaceCarDriver("Nelson Piquet", 300);
  this.raceCarDrivers.Add(raceCarDriver);

  // Select new item
  this.BindingManager.Position = this.BindingManager.Count - 1;
}

private void deleteButton_Click(object sender, EventArgs e) {
  // Remove item from list data source directly
  this.raceCarDrivers.Remove(
    (RaceCarDriver)this.BindingManager.Current);
}

BindingList<T>->IBindingList->IList
BindingList<T> nicely implements the list management (AllowEdit, AllowNew, AllowRemove, and AddNew) and change notification (SupportsChangeNotification, ListChanged) functional subsets of IBindingList.[5] And because it's generic, it can turn any type into a strongly typed list data source with data-binding-savvy list management and change notification using something like the following code

Two-Way Item Change Synchronization

When the values in a DataGridView row are changed, DataGridView automatically replicates the changes to the bound list data source. Similarly, when changes are made to an item in the list data source of BindingList<T>, an item change notification is broadcast to all bound controls.

 

BindingList<T> allows us to use almost any class to create a data-binding-savvy strongly typed list data source. However, some item classes come already associated with their own collection classes. Although any collection class that implements IList can be used as a list data source, you don't get full-flavor data binding if you don't implement IBindingListnamely, support for two-way list and item change notification.

To gain this support and to avoid the highly involved implementation of IBindingList ourselves, we'd love to be able to "upgrade" an existing IList implementation to IBindingList. The class that performs this upgrade for you is BindingSource.

The BindingSource component (from System.Windows.Forms) consumes either item types or list types and exposes them as IBindingList implementations.

 

if you need to implement a VCR-type control to navigate the items in a data source, you don't have to acquire a BindingManager and you don't have to manually create your own navigation methods. Instead, you simply rely on the BindingSource to manage currency and use its currency-oriented methods as required:

 

void moveFirstButton_Click(object sender, EventArgs e)

{ this.employeesBindingSource.MoveFirst(); RefreshItems(); }

 

Master-Detail binding
image

 

Why [STAThread]

When the STAThreadAttribute is applied, it changes the apartment state of the current thread to be single threaded. Without getting into a huge discussion about COM and threading, this attribute ensures the communication mechanism between the current thread and other threads that may want to talk to it via COM. When you're using Windows Forms, depending on the feature you're using, it may be using COM interop in order to communicate with operating system components. Good examples of this are the Clipboard and the File Dialogs.

SingleInstanceApplication

// SingleInstanceApplication.cs
class SingleInstanceApplication : WindowsFormsApplicationBase
{ ... protected override void OnCreateMainForm() { this.MainForm = new MainForm(); }

Friday, March 05, 2010 8:13:20 PM UTC  #    Comments [0]    |   |  Trackback
 Thursday, March 04, 2010

CLR and .NET Framework

The CLR is the runtime for executing managed code. C# is one of several managed
languages that get compiled into managed code. Managed code is packaged into an
assembly, in the form of either an executable file (an .exe) or a library (a .dll), along
with type information, or metadata.

Managed code is represented in Intermediate Language or IL. When the CLR loads
an assembly, it converts the IL into the native code of the machine, such as x86. This
conversion is done by the CLR’s JIT (Just-In-Time) compiler. An assembly retains

almost all of the original source language constructs, which makes it easy to inspect
and even generate code dynamically.

The CLR performs as a host for numerous runtime services. Examples of these services
include memory management, the loading of libraries, and security services.
The CLR is language-neutral, allowing developers to build applications in multiple
languages (e.g., C#, Visual Basic .NET, Managed C++, Delphi.NET, Chrome .NET,
and J#).

 

 

How the Garbage Collector Works:

The GC begins with its root object references, and walks the object graph, marking
all the objects it touches as reachable. Once this process is complete, all objects that
have not been marked are considered unused, and are subject to garbage collection.
Unused objects without finalizers are immediately discarded; unused objects with
finalizers are enqueued for processing on the finalizer thread after the GC is complete.
These objects then become eligible for collection in the next GC for the object’s
generation (unless resurrected).

 

The remaining “live” objects are then shifted to the start of the heap (compacted),
freeing space for more objects. This compaction serves two purposes: it avoids

memory fragmentation, and it allows the GC to employ a very simple strategy when
allocating new objects, which is to always allocate memory at the end of the heap.
This avoids the potentially time-consuming task of maintaining a list of free memory
segments.

 

If there is insufficient space to allocate memory for a new object after garbage
collection, and the operating system is unable to grant further memory, an
OutOfMemoryException is thrown.

 

Generational collection
The most important optimization is that the GC is generational. This takes advantage
of the fact that although many objects are allocated and discarded rapidly, certain
objects are long-lived and thus don’t need to be traced during every collection.
Basically, the GC divides the managed heap into three generations. Objects that have
just been allocated are in Gen0 and objects that have survived one collection cycle
are in Gen1; all other objects are in Gen2.

 

The large object heap
The GC uses a separate heap called the Large Object Heap (LOH) for objects larger
than a certain threshold (currently 85,000 bytes). This avoids excessive Gen0
collections—without the LOH, allocating a series of 16 MB objects might trigger a
Gen0 collection after every allocation.

The LOH is not subject to compaction, because moving large blocks of memory
during garbage collection would be prohibitively expensive. This has two
consequences:

1. Allocations can be slower
2. The LOH is subject to fragmentation

The large object heap is also nongenerational: all objects are treated as Gen2.

 

Concurrent and background collection

The GC must freeze (block) your execution threads for periods during a collection.
This includes the entire period during which a Gen0 or Gen1 collection takes place.
The GC makes a special attempt, though, at allowing threads to run during a Gen2
collection

 

Forcing Garbage Collection (not recommend)

GC.Collect()

 

A good guideline is to implement IDisposable yourself if any field in your class is assigned an object that implements IDisposable. (Such as System.Timers.Timer)(System.Threading.Timer is different)

 

Monitor the memory leaks: long memoryUsed = GC.GetTotalMemory (true);

 

Occasionally, it’s useful to hold a reference to an object that’s “invisible” to the GC
in terms of keeping the object alive. This is called a weak reference, and is implemented
by the System.WeakReference class.

 

One use for WeakReference is to cache large object graphs.
http://www.shafqatahmed.com/2008/01/weakreference-b.html

 

 

Asynchronous Methods

asynchronous programming model or APM

An asynchronous method aims never to block any thread, instead using a pattern of
returning with a callback.

 

The end goal of the APM is thread economy.

The purpose of asynchronous methods isn’t to
provide a convenient mechanism for executing a method in parallel with the caller;
it’s to optimize thread resources.

 

Here’s the golden rule of the APM: Make good use of the CPU, or exit with a callback!

 

The primary use for asynchronous methods is handling many potentially longrunning
concurrent requests—typically over slow network connections.

 

IAsyncResult BeginXXX (in/ref-args, AsyncCallback callback, object state);
return-type EndXXX (out/ref-args, IAsyncResult asyncResult);
public delegate void AsyncCallback (IAsyncResult ar);

 

To avoid blocking, you will nearly always call the EndXXX method from inside the
callback method. Callbacks always run on pooled threads.

 

image

 

http://en.csharp-online.net/CSharp_Delegates_and_Events%E2%80%94Asynchronous_method_calls
http://msdn.microsoft.com/en-us/library/h80ttd5f.aspx

Collections

ICollection Properties

image

image

IComparer
Copmare method

IEqualityComparer
GetHashCode, Equals

SortedList calss is a dictionary.

Race conditions and deadlocks

http://support.microsoft.com/kb/317723

A race condition occurs when two threads access a shared variable at the same time. The first thread reads the variable, and the second thread reads the same value from the variable. Then the first thread and second thread perform their operations on the value, and they race to see which thread can write the value last to the shared variable. The value of the thread that writes its value last is preserved, because the thread is writing over the value that the previous thread wrote.

A deadlock occurs when two threads each lock a different variable at the same time and then try to lock the variable that the other thread already locked. As a result, each thread stops executing and waits for the other thread to release the variable. Because each thread is holding the variable that the other thread wants, nothing occurs, and the threads remain deadlocked.

Thursday, March 04, 2010 7:57:29 PM UTC  #    Comments [0]    |   |  Trackback
 Wednesday, March 03, 2010
 Monday, March 01, 2010

http://learn.iis.net/page.aspx/140/understanding-the-built-in-user-and-group-accounts-in-iis-70/

In previous versions of IIS, we had a local account created at install time called IUSR_MachineName. The IUSR_MachineName account was the default identity used by IIS whenever anonymous authentication was enabled. This was used by both the FTP and HTTP services. 

There was also had a group called IIS_WPG, used as a container for all the application pool identities. We made sure all the appropriate resources on the system had the correct permissions set for the IIS_WPG group during IIS setup so that an administrator only needed to add their identity to that group when they created a new application pool account.

This model worked well, but had its drawbacks: the IUSR_MachineName account and IIS_WPG group were both local to the system it was created on. Every account and group within Windows is given a unique number called a SID (security identifier) that distinguishes it from other accounts. When an ACL is created only the SID is used. As part of our design in previous versions of IIS, we had included the IUSR_MachineName in the metabase.xml file so that if you tried to copy the metabase.xml from one machine to another, it would not work--the account on the other machine would have a different name.

In addition, you could not just 'xcopy /o' ACLs from one machine to another since the SIDs were different machine to machine. A work around was to use domain accounts--but that required adding an active directory to the infrastructure. The IIS_WPG group had similar issues with permissions. If you set ACLs on one machine's file system for IIS_WPG and tried to 'xcopy /o' those over to another machine, it would fail. The IIS team heard this feedback and improved this experience by using a built-in account and group in IIS 7.0.

A built-in account and group are guaranteed by the operating system to always have a unique SID. IIS 7.0 has taken this further and ensured the actual names used by the new account and group will never be localized. For example, regardless of the language of Windows you install, the IIS account name will always be IUSR and the group name will be IIS_IUSRS.

In summary, IIS 7.0 offers:

  • The IUSR built-in account replaces the IUSR_MachineName account
  • The IIS_IUSRS built-in group replaces the IIS_WPG group

Since the IUSR account is a built in account, it no longer needs a password. Logically, think of it as being the same as NETWORKSERVICE or LOCALSERVICE accounts. Both the new IUSR account and IIS_IUSRS group are discussed in greater depth in the sections below.

Monday, March 01, 2010 4:31:47 PM UTC  #    Comments [0]    |  Trackback
 Thursday, February 25, 2010
 Tuesday, February 23, 2010

http://msdn.microsoft.com/en-us/magazine/cc163403.aspx

http://www.codeproject.com/KB/office/MyContacts.aspx

http://www.outlookcode.com/news.aspx?id=22

http://msdn.microsoft.com/en-us/library/bb608610.aspx

http://msdn.microsoft.com/en-us/library/bb608615.aspx

http://msdn.microsoft.com/en-us/library/bb772084.aspx
http://social.msdn.microsoft.com/Forums/en-US/vsofficetools2008prerelease/thread/07144243-d59e-448e-a9b9-04ddbf9b58dc

Add a button to context menu
http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/8cb73784-ce61-46e8-9241-25f67bdc5e99
http://social.msdn.microsoft.com/forums/en-US/vsto/thread/74e3fbaf-5806-4684-b410-65a0720386e8/

VSTO FAQ
http://social.msdn.microsoft.com/Forums/en/vsto/thread/31b1ffbf-117b-4e8f-ad38-71614437df59/?ffpr=0

FaceId Property http://www.kebabshopblues.co.uk/2007/01/04/visual-studio-2005-tools-for-office-commandbarbutton-faceid-property/

Very Good Blog http://jake.ginnivan.net/tag/vsto/ 

Build Office-Based Solutions Using WPF, WCF, And LINQ http://msdn.microsoft.com/en-us/magazine/cc163292.aspx
Using WPF With VSTO & Office 2007 http://xamlcoder.com/cs/blogs/joe/archive/2007/07/17/using-wpf-with-vsto-office-2007.aspx

Programmatically Adding a Column to Your Outlook 2007 Inbox Table View http://blogs.msdn.com/bali_msft/archive/2008/11/04/programmatically-add-a-column-in-your-outlook-2007-inbox-table-view.aspx
http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/d695b85f-39c3-4ff7-a528-54c029cdba8e/
http://social.msdn.microsoft.com/forums/en-US/vsto/thread/30ca71bf-b60c-4ed1-85de-0aa739f5ddd1/

Task Panel
http://msdn.microsoft.com/en-us/vbasic/cc338005.aspx
http://msdn.microsoft.com/en-us/library/bb296010.aspx
http://msdn.microsoft.com/en-us/library/bb608590.aspx
http://msdn.microsoft.com/en-us/library/aa942864%28VS.80%29.aspx

Tuesday, February 23, 2010 6:25:05 PM UTC  #    Comments [0]    |   |  Trackback
 Sunday, February 21, 2010
Sunday, February 21, 2010 7:19:58 AM UTC  #    Comments [0]    |  Trackback
Copyright © 2010 Kevin Mocha. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.
Pick a theme: