DCSIMG
December 2008 - Posts - Pini Dayan

Pini Dayan

The best thing about a boolean is even if you are wrong, you are only off by a bit.

December 2008 - Posts

Encrypting and decrypting sensitive data in your web.config files using Protected configuration - Part III

In the last 2 posts, Part I and Part II  I wrote the general idea and how to implement the protected configuration.The reason I started to learn this subject was actually  the need to encrypt application blocks section with Entlib 4.1. So here is how to are implementing the following scenario:

Suppose you have an application using the Entlib. And suppose you are using the DAAB. The DAAB contains in it's configuration a connection string that you wish to encrypt. Not only that, you also wish to deploy your application to several servers ( A web farm).

Here are the steps to accomplish this mission:

1. Create a web application , lets call it EncryptTest. This application has only a single page. default.aspx. Add an application to your IIS and map it to the created web application.

2. Right click the web.config and open the Entlib configuration tool.

3. Add the Data Access application block and set some connection string.

image

4. Create a new key container  using the cmd command :

aspnet_regiis -pc "MySampleKeys"–exp

5. Open the machine.config file and add the key key :

<add name="RsaProtectedConfigurationProviderqqq" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="MySampleKeys" cspProviderName="" useMachineContainer="true" useOAEP="false"/>

Notice that the name is a new name and that the keyContainerName is the name of the key container we created at step 4.

5. Go back to the configuration tool of the Entlib and in the properties of the DAAB choose the new name I in my sample this is the RsaProtectedConfigurationProviderqqq).The entlib has a design time support , so if you cant see the new name , simply close the IDE and reopen it.
image

6. Now in your code check that everything works. For instance run these 2 lines of code in the Page_Load event of your app:

Microsoft.Practices.EnterpriseLibrary.Data.Database oDB = Microsoft.Practices.EnterpriseLibrary.Data.DatabaseFactory.CreateDatabase("MyDSN");
      Response.Write(oDB.ConnectionString);

7. Export the key container using the command:

aspnet_regiis -px "MySampleKeys" keys.xml. You now have an xml file you can import to other computer. Copy this xml file to the servers.

8. Import the key container using the command

aspnet_regiis -pi "MySampleKeys" keys.xml ( specify the path to the keys.xml file).

9. Grant permission to this key container if you need to.

10. Finally add the new entry to the machine.confige as you did in step 5.

Enjoy.

Posted: Dec 30 2008, 12:42 PM by Pini Dayan | with 2 comment(s) |
תגים:,

Encrypting and decrypting sensitive data in your web.config files using Protected configuration - Part II

In the previous post I showed how to encrypt the sensitive data in my web.config using the ASP.NET protected configuration feature. Lets continue.

What are User level and Machine level key containers.

From msdn :"User-level RSA key containers are stored with the Windows user profile for a particular user and can be used to encrypt and decrypt information for applications that run under that specific user identity. User-level RSA key containers can be useful if you want to ensure that the RSA key information is removed when the Windows user profile is removed. However, because you must be logged in with the specific user account that will make use of the user-level RSA key container in order to encrypt or decrypt protected configuration sections, they are inconvenient to use.

Machine-level RSA key containers are available to all users that can log in to a computer, by default, and are the most useful as you can use them to encrypt or decrypt protected configuration sections while logged in with an administrator account. A machine-level RSA key container can be used to protect information for a single application, all the applications on a server, or a group of applications on a server that run under the same user identity. Although machine-level RSA key containers are available to all users, they can be secured with NTFS Access Control Lists (ACLs) so that only required users can access them."

"You identify an RSA key container as a user-level key container with the -pku option; otherwise, the RSA key container is considered a machine-level container."

OK, so we have created the key container and we need to export it to more machines

The next step i want to show is how to use this machine level key container to more machines. This scenario is good when you application is in a web farms and it needs to share the same keys for the encryption decryption process.

In order to export the container file we have created earlier we will use the command:

aspnet_regiis -px "MySampleKeys" keys.xml -pri . where -px is an option telling the tool to export the container keys by the name. In order to export the private key as well ( the one that decrypts the data) use the -pri option.

Now we need to import this file to the servers we wish sharing the same keys.

 

For summary, the steps we need to create, export and import on a different server:(I found in some blog)

1. Create a machine-level RSA key container on the encrypting machine.

Example : aspnet_regiis -pc "MySampleKeys"–exp


2. Define the attributes of an instance of the RSA protected configuration provider, that uses the RSA key container created in the previous step, in the web.config file.

Example:

</configSections>  
<configProtectedData defaultProvider="SampleProvider">
  <providers>
    <add name="SampleProvider" 
      type="System.Configuration.RsaProtectedConfigurationProvider, 
            System.Configuration, Version=2.0.0.0, Culture=neutral, 
            PublicKeyToken=b03f5f7f11d50a3a,
           processorArchitecture=MSIL"
      keyContainerName="MySampleKeys" 
      useMachineContainer="true" />
  </providers>
</configProtectedData>


3. Encrypt the relevant web.config section(s) using the RSA protected configuration provider  instance defined in the previous step.

Example: aspnet_regiis -pe "connectionStrings" -app "/website1"

Dont forget to grant access to the process identity. (By the way the simplest way to know what is the process identity is to write to the scree the System.Security.Principal.WindowsIdentity.GetCurrent().Name).


4. Export both the public and private keys from the RSA key container created in step 1. The public key is used to encrypt configuration data and the private key is required to decrypt it.
5.On the decrypting machine or machines, import both the public and private keys, exported in the previous step, into an RSA key container with the same name as the container on the encrypting machine.

Example: aspnet_regiis -px "MySampleKeys" keys.xml -pri

The file looks like this:

<RSAKeyValue>
  <Modulus>mYZNaEAAp6PodWwYcj0te43FbX8F8LUb6e2RbI7aWquY/+C2LvdjRvTlHIUhv0wcy4Xm7IwUNWoa
  VsfJ+lKRgo3sPJ9pOtrP6xH+9PWbFl13dZP/GCFDo+9mpc5NaIFrrd+CHdz6BQs7sEzwPDn5o4IQlEFl+RrTQZUTWjh+8Cs=
  </Modulus>
  <Exponent>AQAB</Exponent>
  <P>zU0hsYyFHYZcxHzShRp1Pyb4gdkYVSVPscmX9ptbj9Knm4jc8Rq6fde1pzKb7zrq/319rb27zcsFhGzVg3KhLQ==</P>
  <Q>v2/rdGza/JJ6HlFZompiZpaAL5qD/L98DMshwM3aH9EF3gfIjXWD+/LGEdhSDMiFzVLPHI8vmkF40TDqMX49tw==</Q>
  <DP>wxhkR3xY15jiuVpBGHnvJ4daKtLqe6eMV1BS1+gFF+TAoF5sT7btuD7wAiZm5u1felF/yEaAnO0sng5qzJJ3NQ==</DP>
  <DQ>R+AfiSDtv3LHguaMPtyugVH0Yusirxy92JfT3m3rfZKfH1PQyrvaiBgIod6UP9Rx2DtFI7Xm64W1dOVmqJp7VQ==</DQ>
  <InverseQ>Hpn8yd0+v7MqgCaj7c1StKhEsDYaaFpolzL9/CmDbnUc09p5Ub9vf86quX9XKDR1a0RWa1caX1+AoZ1YJaPekQ==</InverseQ>
  <D>IjHEqfSfcLdUPlseMsunhr5z+8hwBUYBep/8ZQaIYeuYf12IlntpdFN1eF26v4XvX/FqFsO
  4eJEyXqPPO98KI4alANj2be3AmVFNd1xXng6D8WxwDtqIUHTHPON4Xk1VU6lhGCNHQgABC+npB
  /1LCc5PC9veC6wHE1PeGNU2Xmk=</D>
</RSAKeyValue>


6. Import the key container to the destination machine using the command: aspnet_regiis -pi "MySampleKeys" keys.xml.

On the decrypting machine or machines, grant read access to the newly create RSA key container to the Windows identity of the relevant web application. 

This is for Machine level key container. All that left to do is to add the new key to the machine config like in step  2.

Enjoy.

Encrypting and decrypting sensitive data in your web.config files using Protected configuration - Part I

We can use the "Protected configuration" feature of the ASP.NET when we want to encrypt a sensitive data stored in our web.config file, such as username, passwords and of course our connection string. The advantage of securing our sensitive data is obvious: we are making it difficult for an attacker to gain access to this sensitive data even if he got access some how to our web.config file. 

Here is a sample for a non encrypted data stored in this web.config file:

<configuration>
  <connectionStrings>
    <add name="MySqlServer" connectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind111;" />
   </connectionStrings>
</configuration>

When I will encrypt my data the same data only encrypted will look something like this:

<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w
3.org/2001/04/xmlenc#rsa-1_5" /> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>RSA Key</KeyName> </KeyInfo> <CipherData> <CipherValue>RXO/zmmy3sR0iOJoF4ooxkFxwe
lVYpT0riwP2mYpR3FU+r6BPfvsqb384pohivk1237Dm4lPgR2bE9F7k6TblLVJFvnQu7p7d/yjnhzgHw
WKMqb0M0t0Y8DOwogkDDXFxs1UxIhtknc+2a7UGtGh6Di3N572qxdfmGfQc7ZbwNE= </CipherValue>
</CipherData> </EncryptedKey> </KeyInfo> <CipherData> <CipherValue>KMNKBuV9nOid8pUvdNLY5I8R7BaEGncjkwYgshW8ClKjrXSM7zeIRmAy/cTaniu8Rfk92KV
kEK83+UlQd+GQ6pycO3eM8DTM5kCyLcEiJa5XUAQv4KITBN
BN6fBXsWrGuEyUDWZYm6Eijl8DqRDb11i+StkBLlHPyyhbnCAsXdz5CaqVuG0obEy2x
mnGQ6G3Mzr74j4iffnyvRq7levA2sBR4lhE5M80Cd5
yKEJktcPWZYM99TmyO3KYjtmRW/Ws/XO3z9z1b1KohE5Ok/YX1YV0+Uk4/yuZo0
Bjk+rErG505YMfRVtxSJ4ee418ZMfp4vOaqzKr
SkHPie3zIR7SuVUeYPFZbcV65BKCUlT4EtPLgi8CHu8bMBQkdWxOnQEIBeY+TerAee/SiBCrA8M/n9
bpLlRjjjb+URiGLoaj+XHym//fmCclAcveKlba6vKrcbqhEjsnY2F
522yaTHcc1+wXUWqif7rSIPhc0+MT1hB1S
123AdmPgtZUyzcL51DoChy+hZ4vLzE= </CipherValue> </CipherData> </EncryptedData> </connectionStrings>

The nice thing is that when your code executes , the data will be decrypted and then can use the sensitive data (in this sample the connection string).

So how do we make this encryption magic to work? We use the good old aspnet_regiis.exe tool installed when we install the .NET Framework.

This utility is installed under the %SystemRoot%\Microsoft.NET\Framework\versionNumber folder and it include several options for encrypting portions of the web.config file, decrypting options, creating keys from the containers or adding new ones( i will explain about the keys later).In addition we may need to grant our running process the authorization to access these keys, this is also being done using this tool.

As in many of the ASP.NET features such as Membership, State management and much more , this feature also works in the Provider Model. (Plug and play provider code to use different data store for instance in case of membership)

More on the provider model :http://msdn2.microsoft.com/en-us/library/Aa479030.aspx

The base class of this provided feature is ProtectedConfigurationProvider which is new in .NET 2.0, The 2 provider we can use out of the box are:

I will later explain when to use which one, but for now remember that if your application is about to be in a web farm (on several computers) then you need to use the RsaProtectedConfigurationProvider that enables you to export and import the keys of the RSA algorithm used to encrypt your data from one machine to another.

A few words about the RSA and Asymmetric encryption:

When we wish to encrypt and decrypt data we can use 2 options:

1. The symmetric way which uses the same key for encrypting data and decrypting data.(The known algorithms for this way are: DES, RC2, TripleDes and of course Rijndael)

2. The Asymmetric way which uses 2 different keys , one for encryption and the other for decryption. These 2 keys are called the private key and the public key.The private key is kept secret, while the public key may be widely distributed.The knows RSA algorithm is an example of such a way.

For more details on that issue see:http://en.wikipedia.org/wiki/Symmetric_cipher and http://en.wikipedia.org/wiki/Public-key_cryptography

So , how do we specify which Provider we want to use:

We first need to add the provider we want to use to our we.config file, like this:

<configProtectedData>
    <providers>
      <add name="MyProvider"
        type="System.Configuration.RsaProtectedConfigurationProvider, 
              System.Configuration, Version=2.0.0.0, Culture=neutral, 
              PublicKeyToken=b03f5f7f11d50a3a,
             processorArchitecture=MSIL"
        keyContainerName="MySampleKeys"
        useMachineContainer="true" />
    </providers>
  </configProtectedData>

The name of the provider provider, "MyProvider" will be uised later for the config section we want to encrypt.  The ketcontainername is also very important,it is the name of the RSA key container used to encrypt or decrypt the contents of the Web.config file. In addition it is important to note that the running process must have read rights to read from this container.(I will show how to grant these rights later).

For more details on that issue see: http://msdn.microsoft.com/en-us/library/68ze1hb2(VS.80).aspx

OK, So we chose the provider we want, how do we actually encrypt the data:

This is the time to start using the aspnet_regiis.exe too.but first we need to create our key container that holds the keys for the RSA encryption decryption.

To create the key container ( when using the RsaProtectedConfigurationProvider provider), we will use the -pc option when using the aspnet_regiis.You must also specify the name of the container and tell the tool if you wish to export it later using the -exp option. Here is a sample on how to create this container:

aspnet_regiis -pc "MySampleKeys"–exp

Notice that the MySampleKeys name is the one in the keyContainerName. After you have created the key container, you need to grant access to the place where the container is at (These are ACLs) .So , if you are using ASP.NET you need to grant the process identity a read right.To grant this authorization you need to use the -pa option on the aspnet_regiis.

aspnet_regiis -pa "MySampleKeys" "NT AUTHORITY\NETWORK SERVICE".There is a difference between user level keys and machine level keys I will explain later.

For more information see http://msdn.microsoft.com/en-us/library/zhhddkxy(VS.80).aspx

OK, so we have created our key container and did not use the default one(we can do this as well , my guess is that this is exactly what the Entlib does).Now lets encrypt the config section we want to secure,For this purpose lets use the -pe option on the aspnet_regiis.

aspnet_regiis -pe "connectionStrings" -app "/website1"  where website1 is the name of the application in the IIS. 

Assembly versions management

What is Assembly version and how to control it?

Each assembly has a version number. The version number can be found in the AssemblyInfo.cs file in your VS.NET project. This file contains general information about the assembly using set of attributes such as: AssemblyTitle, AssemblyDescription, and of course AssemblyVersion.

AssemblyVersion attribute specifies the version number of the assembly.

(Unlike AssemblyFileVersion which will be explained later)

The format for the Assembly version is: <major version>.<minor version>.<build number>.<revision>

From msdn:

Major : Assemblies with the same name but different major versions are not interchangeable. This would be appropriate, for example, for a major rewrite of a product where backward compatibility cannot be assumed.

Minor : If the name and major number on two assemblies are the same, but the minor number is different, this indicates significant enhancement with the intention of backward compatibility. This would be appropriate, for example, on a point release of a product or a fully backward compatible new version of a product.

Build : A difference in build number represents a recompilation of the same source. This would be appropriate because of processor, platform, or compiler changes.

Revision : Assemblies with the same name, major, and minor version numbers but different revisions are intended to be fully interchangeable. This would be appropriate to fix.

It's important to note that these numbers mean whatever you want them to mean, that is you can say: "These changes are huge and important so I will change my major version number". Or you could say: "Well these features are not that important so I will change my minor version".

So we will change the major or minor version numbers when we do a change that is not compatible with the code before, such as : adding or removing parameters to a function.

We will change the build and revision version numbers when the changes are like bug fixes or internal code changes.

In order to control the version you can use the AssemblyVersion in the following ways:

1. Specify the entire version number such as:

[assembly:AssemblyVersion("1.3.250.1")]

This will specify that the major version is 1, the minor version is 3, the build version is 250 and that the revision number is 1.

2. Specify the major and minor versions only:

[assembly:AssemblyVersion("1.3.*")]

This will specify that the major version is 1, the minor version is 3and the build and revision are the defaults.

3. Specify only the major minor and build such as:

[assembly:AssemblyVersion("1.3.25.*")]

This will specify that the major version is 1, the minor version is 3, the build version is 25 and the revision version is defaults.

The defaults are being calculated like this:

If the version attribute is set to "1.0".*" the vs.net will calculate the version number as: 1.0.X.Y where X is the number of days since 1/2/2000 and Y is the number of seconds since last midnight divided by 2. Simple right?

Assembly version number at runtime:

The assembly's version number, which, together with the assembly name and culture information, is part of the assembly's identity. The number is used by the runtime (The CLR) to enforce version policy and plays a key part in the type resolution process at run time.

Note: When the assembly is one without a strong name there is no version checking. So the runtime will not look for an assembly in the GAC if there it doesn't have a strong name.

When two assemblies differ in their version number, they are considered by the runtime to be completely different assemblies.

Version checking only occurs with strong-named assemblies.

The version of a referenced Assembly is part of the clients manifest (as well as the public key token). So When the runtime tries to locate an assembly (This process is called probing) it (the CLR) checked that the Assembly it tries to load is identical to the one which the application was built with.

Here is a sample of such a client's manifest with a reference to a shared assembly:

clip_image003

When a client application adds the shared assembly as its reference, the shared assembly’s public token as well as the version number are recorded at the client’s manifest.

Let's see an example of this:

Let's say we have a Class library project called 2, and in the AssemblyInfo we are writing:

[assembly: AssemblyVersion("1.0.0.1")]

And let's say we have a Console Application named 1 which has a reference to the 2.dll file from our Class library project called.

Now suppose we deployed this 1 Application , and there is no 2.dll in its bin folder, but there is a 2.dll in the GAC. If we try to run this app everything is just fine. But if you change the version number to:

[assembly: AssemblyVersion("1.0.0.2")] and insert this new complied dll to the GAC, and try to rerun our 1 application, we get the following error:

clip_image005

I won't go into much details of the Probing algorithm the CLR does but for the interested readers here are some links explaining just that:

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

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

Assembly file version:

There is another attribute called AssemblyFileVersion. This is the attribute you see when you right click the dll or exe file and see the versionclip_image007

As you can see, the Assembly version can be seen also in the "other version information" box.

If you want your Assembly to be backward compatible don’t change the AssemblyVersion. use the AssemblyFileVersion to track your builds and versions.

More useful references:

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

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

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

http://www.codeproject.com/KB/dotnet/ManagingAssemblyVersions.aspx?fid=52366&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=1690681

Microsoft Ajax: Table of content

Hi all, For better knowing which post explain which part of Ajax and Microsoft ASP.NET Ajax here is a table of content with all the links in the serious of post regarding Ajax:

what is Ajax , why do we need it and how we used to write Ajax based web applications:

what is Ajax

What is JSON and how to use it when writing Ajax based web applications:

Ajax improvements using JSON

What it actually Microsoft AJAX , how to use it and what is UpdatePanel control we here so often about:

Introducing Microsoft Ajax

What is the UpdateProgress control and how to use it in combine with the UpdatePanel control:

UpdateProgress control

Complete the server side controls we can use in Microsoft ASP.NET Ajax:The  Timer control , The ScriptManager and ScriptManagerProxy

Timer,ScriptManager and ScriptManagerProxy controls

How to call web service code from client side using Microsoft Ajax and how get the same effect without using web services using the new PageMethods technique:

Microsoft Ajax  - How to use web service and PageMethods

This part explains the client half of Microsoft Ajax, What it contains and how to use it. In addition this part also explains JavaScript namespaces and new Object types in the Ajax framework.

Microsoft Ajax - Client Side

More on the client half of Microsoft Ajax. This time i will explain how did Microsoft Ajax framework extended the built- in types like Boolean,String , Int.

Microsoft Ajax - Client Side continued

More on the client half of Microsoft Ajax. How to manage history when performing partial updates.                     

Microsoft Ajax - Client Side continued continued

 

Pini Dayan

 

 

How to make VS.NET 2008 to support WSE 3.0

I found out yesterday that i cant consume a web service with WSE 3.0 capabilities. Well actually it's not that i cant consume, but that when i am adding a Web Reference to the web service i see only the proxy class without the WSE support.

So how do trick my VS.NET 2008 to know my proxy class ( lets say the name of this class is ServiceWse)

Here is how:

  • In order to trick VS.NET 2008 I am creating a simple project in VS.2005 , it can a Windows form project or a Console Application project.
  • I then right click my project and choosing the WSE 3.0 setting and checking the check box telling my project ( and modifying my app.config) to work with WSE.
  • I then add the Web Reference to my WSE enabled web service.
  • After doing that i have a Web reference folder under my project folder. Copy it and paste it in your VS.NET 2008 project instead of the one you added before ( The one that did not have any WSE support)
  • Modify the proxy cs code to make your namespaces and built your project

That's it, now you have a fully functional WSE enabled proxy class.

By the way , don't forget to tell your project in VS.NET 2008 to support this WSE 3.0 settings ( just open the app.config file using the WSE 3.0 config editor tool, since VS.NET 2008 does not support this tool in it's context menu)

Enjoy, Pini Dayan

Where did the "Add Web Reference" disappear????

I am writing some code now days that does an extensive use with the WCE 2.0, don't ask why.

Anyway the consumer of the web service is a .NET 3.5 application (Windows app and web app) so I tried adding a web reference in the only way I know, using the "Add web reference" from the project's context menu. I was amazed to see that the menu option disappeared.

If you don't remember what i am talking about, here is the menu from vs.net 2005:

image 

So I understood that the reason for that is because WCF service is backward compatible with asmx (web services) and i can simply add this reference from the "Add Service Reference" if i want. What i mean is that the communication abilities of web services are part of the WCF abilities.

So i sought the only way to do it is to use the WSDL.EXE utility that still exists. but then i foung out that if you select "Add Service Reference" , you get this menu:

image

If you look the the left bottom side , and click the "Advanced" button, you get the menu:

image

And here it is!!!! on the left bottom side you get the missing "Add Web Reference". 

Microsoft Ajax, from the bottom up - part 9 (and last)

Hi everyone, This is the last post i am going to write in this scope of ASP.NET Ajax. The post will talk about the History capabilities ASP.NET Ajax has to offer. but first of all, here are the list to the previous posts on the subject of ASP.NET Ajax.

Microsoft Ajax, from the bottom up

Microsoft Ajax, from the bottom up - part 2.

Microsoft Ajax, from the bottom up - part 3

Microsoft Ajax, from the bottom up - part 4

Microsoft Ajax, from the bottom up - part 5

Microsoft Ajax, from the bottom up - part 6

Microsoft Ajax, from the bottom up - part 7

Microsoft Ajax, from the bottom up - part 8

So why do we need any support for the back or forward button of our browser? Very simple, for instance, say we have a page with a grid in it (an asp.net Grid control) and this grid supports sorting among other thing. Now lets say this grid is inside an UpdatePanel control. There will be no postbacks and no flickering in the page. So after some column headers were clicked and the table was sorted, if i press the back button on my browser i will be navigated to the previous page i was at and not to the same page with other sorted state i was at. Sometimes this is not what i want to accomplish. I do want to be able to navigate threw the sorted states of my page.

This is exactly what i will show in this post. So make things simpler lets so a simpler example. This example has 3 buttons, each one is doing a postback and update some Label to the Text on the Button.

Here it is:

  image

And here is the code behind:

public void ButtonClick(object sender, EventArgs e)
{
       LabelHistoryData.Text = ((Button)sender).Text;        
}    

Simple aspx page, right? Needless to say these buttons are triggers to some UpdatePanel.all the buttons OnClick is pointing to the same server side event handler. Now lets say Inavigated from www.google.com to this page and clicked each one of the buttons. Clicking the back button on my browser will take me back to Google. What if i want to move between the states of my postbacks?

Here is how i will do it:

 <asp:UpdatePanel ID="UpdatePanel1" runat="server">
                <Triggers>
                    <asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" />
                    <asp:AsyncPostBackTrigger ControlID="Button2" EventName="Click" />
                    <asp:AsyncPostBackTrigger ControlID="Button3" EventName="Click" />
                </Triggers>
                <ContentTemplate>
                    <asp:Panel runat="server" CssClass="box" ID="Content" Height="40px">
                        Date and Time:
                        <%= DateTime.Now.ToLongTimeString() %>
                        <br />
                        Page's refresh state:
                        <asp:Label runat="server" ID="LabelHistoryData" />
                    </asp:Panel>
                </ContentTemplate>
            </asp:UpdatePanel>
            <p />
            <asp:Button runat="server" ID="Button1" Text="Key 1" OnClick="ButtonClick" />
            <asp:Button runat="server" ID="Button2" Text="Key 2" OnClick="ButtonClick" />
            <asp:Button runat="server" ID="Button3" Text="Key 3" OnClick="ButtonClick" />

Here I have the same  UpdatePanel control as before but look at the ScriptManager

<asp:ScriptManager runat="server" ID="ScriptManager1" 
              OnNavigate="OnNavigateHistory" 
              EnableHistory="true" />

Here i am telling the ScriptManager to support the History feature and that when the user clickes back or forward the event handler taking place is "OnNavigateHistory".

In addition every time the button is clicked , i am adding a logical entry point to my url:

// On button click, handle the event and set a history point. 
 public void ButtonClick(object sender, EventArgs e)
 {
   LabelHistoryData.Text = ((Button)sender).Text;
   ScriptManager1.AddHistoryPoint(key, LabelHistoryData.Text, LabelHistoryData.Text);        
 }    

When the page is renders after the buttons event handler the url now looks like this:

http://localhost/AdvancedJS/Ajax/MSAjaxHistory1.aspx#&&s=Key+2
http://localhost/AdvancedJS/Ajax/MSAjaxHistory1.aspx#&&s=Key+3

and when i am pressing the back button i am getting this logical entry points and doing whatever i want with them. typically to return to the state I want :

// Handle the Navigate event
public void OnNavigateHistory(object sender, HistoryEventArgs e)
{
   LabelHistoryData.Text = Server.HtmlEncode(e.State[key]);
}

We can achieve this affect using client side code only but may be i will show this sometime later.

Anyway guys and girls , There is a lot more to say about Microsoft ASP.NET Ajax framework , but I hope you all got the picture. I am using it a lot. Hope my posts helped.

Pini Dayan.

Microsoft Ajax, from the bottom up - part 8

Hi all ,In the last post i wrote that the ASP.NET Ajax on it's client half extended all its native types and added some new functionality to them, such as the trim method to the String object and so on. So lets take a look on how they did it. but first here are the links to the previous posts on the subject.

Microsoft Ajax, from the bottom up

Microsoft Ajax, from the bottom up - part 2.

Microsoft Ajax, from the bottom up - part 3

Microsoft Ajax, from the bottom up - part 4

Microsoft Ajax, from the bottom up - part 5

Microsoft Ajax, from the bottom up - part 6

Microsoft Ajax, from the bottom up - part 7

So , all we need to do in order to get this functionality is simply add a ScriptManager to our asp.net page. Here is a simple example:

function runExample()
      {
          varnewStr = newString("       This is a string   ");
         
          var trimmedStr = newStr.trim();
         
          alert("The string with white spaces removed:"+ trimmedStr + ".");
      }

Simple right? Just don't forget to add the <asp:ScriptManager runat="server" ID="ScriptManager1"> </asp:ScriptManager> line.

So how did they manage to add this functionality? simple, even very simple. All they did is , they used the Prototype property each JavaScript object has.

Every JavaScript object has a property named "prototype" which controls which data members and which method it has. It's like an inheritance chain called the prototype chain. Each object is created based on some other object's prototype. The base prototype is Object.prototype . so each JavaScript object has built in methods (he can even override them) such as the toString, toLocaleString , hasOwnProperty and more. In JavaScript every object is created based on some other object. There are no classes in JavaScript.

So if you wish to add , lets say to the Worker object , another method, here is the way to do it:

function Worker(name,dept)
{
    this.name = name;
    this.dept = dept;
    this.getName = function (){return name };
}

Now if we wish to add another method to this constructor function , we can do it using the prototype property as follow:

Worker.prototype.getDept = function() { return this.dept }

Here are another cool "extension methods" the base types has:

Array.addRange, Array.forEach,

for working with array as a queue: enqueue and dequeue.

String.format, String.endsWith and much more.

Enjoy.

On the next and final post about Microsoft Ajax i will show the History manager the framework has to offer for managing back button when using partial page updates.

 

JavaScript comparison operators : == and ===

When we try to read a language guide book we usually or always skip the operators guide right? I mean , come on , don't we all know how to write JavaScript? What can be simpler then to use the == and != operator in JavaScript like this:

if (str == 'SomeString')
{
   //Do something
}

But as it turns out there are 2 more operators in JavaScript which most developers i know never heard about,The !== and the ===operators. Trying to figure out what is the difference between == and === on the netleads to the following observation:

The == is an operator to check equality, The === is an operator to check identity. Ok but what does it mean exactly. As it turns out the == and the != do type conversion under the hood when they test for equality. (While === and !=== does not!!!)

Here is a simple example of what i am trying to explain

<script>     
   
       alert(5 == "5");   //Prints true
       alert(5 === "5");  //Prints false
   
</script>

This is because the first alert do a type conversion first , which means the String is  converted first to a Number and only then being compared.
The striker === operator does not do any type conversion so the result is false.

Here are a couple more samples

1. null and undefined are both "falsy" values right? so

alert(null == undefined); will result a true because they both converted to boolean first while
alert(null === undefined); will result false.

2. true is converted to 1 and false is converted to 0, so

alert(1== true); will result a true.
alert(1=== true); will result false.

So as you can see === is more striker. It check both value and type.

Hope this helps.

Pini

How to control the naming and sizing of Logging application block flat file listener

Hi all, I have been working lately on building this infrastructure framework for the following services:

  • Data access.
  • Logging.
  • Exception management.
  • Security
  • Caching.

Some of the services i have built are built on top of the Microsoft Enterprise Library version October 2008 (version 4.1). One of the things that bugged me when i implemented the Logging mechanism on top of the Logging Application Block was that i cant control how log files are spread and created. Flat file trace listener and Xml file trace listener simply write to the given file name. This file sometimes need to be viewed (lets say by a parser or viewer i have built) and since this file may grow uncontrolled, i wanted to found a way to "roll" this file into many files according to lets say: The date the file was created or the size of the file.

As it turned out there is a very simple solution.Simply use the Rolling file trace listener.

From the Microsoft Enterprise Library documentation: "Performs logging to a file and rolls the output file when either time or size thresholds are exceeded".

and:

Logging always occurs to the configured file name, and when roll occurs a new rolled file name is calculated by adding the timestamp pattern to the configured file name.

Here is how to configure this trace listener:

1. Create under the Logging application block node for your project configuration the following listener:

image

2. Now configure the file age and the file size you thresholds you want:

image

3. Here are some of the thresholds properties you can configure:

Size Threshold:

You can limit log file growth based on file size.All you need to do is configure the "RoleSizeKB" property to the wanted size in KB. Once the size has elapsed the new file name will be some GUID + the name of the file.The default is zero so make sure you don't leave it this way.

Age Threshold:

The age threshold needs to be configured 1 property, The RolInterval(can be set to Day, Month , Year etc) .

Javascript (or old asp 3) to WCF calls

I have been asked these days to find a solution of how to call WCF service from old asp 3 code , Not ASP.NET, but asp 3. you know: VBScript, option explicit, dim..... :-)

Apparently this is not trivial task at all. If you try to read about it on the net the following "buzzwords" will come up: Pox, REST, RestFull service, WebGet, WebInvoke....

In simple words, POX is a "plain old xml" meaning messages that consist solely of XML payloads without any enclosing SOAP envelope.We will use pox messages when there is no need for the advanced capablities of soap and WS-*, Like when using simple http GET or HTTP POST.

REST means "Representational State Transfer" or in simpler words: how do we use the http principles we already know to call WCF service operations.

This feature is supported only in .NET Framework 3.5, so use this WCF feature after installing the 3.5 version of the .NET Framework.

As you probably know, A WCF service can have many endpoint. Each endpoint has it's own binding. The addresses for these endpoint will be unique for each endpoint, like:

and so on. Each endpoint binding will describe the communication protocol this endpoint agrees on. So why do i need anything special to call this WCF service, why does the wshttpbinding or the basichttpbinding are not good enough?

Well , basically  when we used HTTP GET or HTTP POST up until now , either when using web service nor when we used WCF service , the messages were SOAP messages.We can however send now "clean" xml messages, or simply using the query string to send the date to the WCF service operations.

Another term we need to realize is "Resource", a Resource is identified by URI and is used to uniquely identify an operation.When we used SOAP web services we used a single URI and we added an operation to this URI to specify which operation we wish to invoke. On the other hand "RESTful web service" uses a unique URI to reference every resource, and HTTP verbs to define actions on those resources.

OK, enough with that, lets show some simple WCF service and how we actually communicate with this service.

Here is my WCF Service code:

namespace DemoWCFService
{   
    [ServiceContract]
    public interface IService1
    {       
        [OperationContract]
        string GetsProperty1();

       [OperationContract]        
       [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Xml,
       ResponseFormat = WebMessageFormat.Xml,
       BodyStyle = WebMessageBodyStyle.Wrapped,
       UriTemplate = "/Person")]
       Person GetDTO();

        /// <summary>
        /// This is not working a real post. it still goes to the quesry string
        /// </summary>     
       [OperationContract]
       [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Xml,
       ResponseFormat = WebMessageFormat.Xml,
       BodyStyle = WebMessageBodyStyle.Wrapped  ,
       UriTemplate = "Person2?Property1={sProperty1}&Property2={nProperty2}&Property3={bProperty3}")]        
       Person GetDTO2(string sProperty1, int nProperty2, bool bProperty3);

       [OperationContract]
       [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Xml,
       ResponseFormat = WebMessageFormat.Xml,
       BodyStyle = WebMessageBodyStyle.Wrapped,
       UriTemplate = "Person4?Property1={sProperty1}&Property2={nProperty2}&Property3={bProperty3}")]   
       Person GetDTO4(string sProperty1, int nProperty2, bool bProperty3);

      [OperationContract]
      [WebInvoke(Method="GET",
       UriTemplate = "Person3?Property1={sProperty1}&Property2={nProperty2}&Property3={bProperty3}")]
       int GetDTO3(string sProperty1, int nProperty2, bool bProperty3);
[OperationContract]
[WebInvoke(UriTemplate = "Person5")]
string GetDTO5(Customer c);
       
    }
    
    [DataContract]
    public class Person
    {       
        [DataMember]
        public string sProperty1 = "123";

        [DataMember]
        public int nProperty2 = 123;

        [DataMember]
        public bool bProperty3 = true;
      
    }
}

Note that i have created a WCF service with 5 operations, some of them will be used to explain this sample.
I also created a composite class named "Person" which contains some data members one is of type string, the second is of type int and the third is if type boolean. This will be the DTO(data transfer object) some some of the calls.

The most important code to notice is the WebInvoke attribute on the operations we declared.There is also a WebGet attribute that serve for the  exact purpose only for HTTP GET requests, so no Method parameter should be specified there. 

This attribute  is applied to a service operation in addition to the OperationContractAttribute and associates the operation with a UriTemplate as well as an underlying transport verb that represents an invocation (for example, HTTP POST, PUT, or DELETE).

Notice also for the use of the UriTemplate which provides the mapping between a request URI and an OperationContract and it identifies the named values that are subsequently bound to matching OperationContract method parameters.

Now lets see the WCF service implementation, nothing special here:

namespace DemoWCFService
{     
    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]    
    public class Service1 : IService1
    {
        private Person oPerson = new Person();
       
        public string GetsProperty1()
        {
            return oPerson.sProperty1;
        }

        public Person GetDTO()
        {
            return this.oPerson;
        }

        public Person GetDTO2(string sProperty1, int nProperty2, bool bProperty3)
        {
            return this.oPerson;
        }

        public Person GetDTO4(string sProperty1, int nProperty2, bool bProperty3)
        {
            return this.oPerson;
        }

        public int GetDTO3(string sProperty1, int nProperty2, bool bProperty3)
        {
            return 590;
        }    
    }
}

And finally , here is the asp 3 code (that can be easily be transformed
to JavaScript ajax calls)

 
<%

Set objXMLHTTP = Server.CreateObject("Microsoft.XMLHTTP")

'Set the name Person as it is in the WebInvoke attribute on the WCF service
dim sURL
sURL = "http://localhost./WCFService/Service.svc/pox/Person"

'Built the data object you wish to send
dim sBody   
sBody = "" 

objXMLHTTP.Open "POST", sURL, false
objXMLHTTP.setRequestHeader "Content-type", "application/xml; charset=utf-8"
objXMLHTTP.setRequestHeader "Content-type", "application/soap+xml; charset=utf-8"


objXMLHTTP.Send sBody
strXML = objXMLHTTP.ResponseText
Response.Write("RESPONSE STATUS: " & objXMLHTTP.status &
                 " RESPONSE STATUS TEXT: " & objXMLHTTP.statusText )
Response.Write("<br>" & Server.HTMLEncode(strXML))

Set objXMLHTTP = Nothing

Response.Write("<br><br>")


'Now calling another function on the WCF with parameters
Set objXMLHTTP2 = Server.CreateObject("Microsoft.XMLHTTP")

'Set the name Person as it is in the WebInvoke attribute on the WCF service
dim sURL2
sURL2 = "http://localhost./WCFService/Service.svc/pox/Person2"
sURL2 = sURL2 & "?Property1=somestring&Property2=5555555&Property3=True"

objXMLHTTP2.Open "POST", sURL2, false
objXMLHTTP2.setRequestHeader "Content-type", "application/xml; charset=utf-8"
objXMLHTTP2.setRequestHeader "Content-type", "application/soap+xml; charset=utf-8"
objXMLHTTP2.setRequestHeader "Content-type", "text/xml"


objXMLHTTP2.Send null
strXML2 = objXMLHTTP2.ResponseText
Response.Write("RESPONSE STATUS: " & objXMLHTTP2.status 
            & " RESPONSE STATUS TEXT: " & objXMLHTTP2.statusText )
Response.Write("<br>" & Server.HTMLEncode(strXML2))

Set objXMLHTTP2 = Nothing

Response.Write("<br><br>")

'Now calling another function on the WCF with parameters
Set objXMLHTTP3 = Server.CreateObject("Microsoft.XMLHTTP")

'Set the name Person as it is in the WebInvoke attribute on the WCF service
dim sURL3
sURL3 = "http://localhost./WCFService/Service.svc/pox/Person3"
sURL3 = sURL3 & "?Property1=somestring&Property2=123&Property3=true"

objXMLHTTP3.Open "GET", sURL3, false
objXMLHTTP3.setRequestHeader "Content-type", "application/xml; charset=utf-8"
objXMLHTTP3.setRequestHeader "Content-type", "application/soap+xml; charset=utf-8"

    
objXMLHTTP3.Send 
strXML3 = objXMLHTTP3.ResponseText
Response.Write("RESPONSE STATUS: " & objXMLHTTP3.status 
            & " RESPONSE STATUS TEXT: " & objXMLHTTP3.statusText )
Response.Write("<br>" & Server.HTMLEncode(strXML3))

Set objXMLHTTP3 = Nothing
Response.Write("<br><br>")


'Now calling another function on the WCF with parameters
Set objXMLHTTP4 = Server.CreateObject("Microsoft.XMLHTTP")

'Set the name Person as it is in the WebInvoke attribute on the WCF service
dim sURL4
sURL4 = "http://localhost./WCFService/Service.svc/pox/Person4"

'Built the data object you wish to send
dim sBody4  
sBody4 = "<Person4 sProperty1='somestring' nProperty2=123 nProperty2=true />"

objXMLHTTP4.Open "POST", sURL4, false
objXMLHTTP4.setRequestHeader "Content-type", "text/xml"
objXMLHTTP4.setRequestHeader "Content-type", "application/xml; charset=utf-8"
objXMLHTTP4.setRequestHeader "Content-type", "application/soap+xml; charset=utf-8"

objXMLHTTP4.Send sBody4
strXML4 = objXMLHTTP4.ResponseText
Response.Write("RESPONSE STATUS: " & objXMLHTTP4.status 
            & " RESPONSE STATUS TEXT: " & objXMLHTTP4.statusText )
Response.Write("<br>" & Server.HTMLEncode(strXML4))

Set objXMLHTTP4 = Nothing

Response.Write("<br><br>")
'Now calling another function on the WCF with parameters
Set objXMLHTTP5 = Server.CreateObject("Microsoft.XMLHTTP")

'Set the name Person as it is in the WebInvoke attribute on the WCF service
dim sURL5
sURL5 = "http://localhost./WCFService/Service.svc/pox/Person5"

'Built the data object you wish to send
dim sBody5  
sBody5 = "<Customer><ID>123</ID><Name>Demo User111121212</Name></Customer>"

objXMLHTTP5.Open "POST", sURL5, false

objXMLHTTP5.setRequestHeader "Content-type", "application/xml; charset=utf-8"


objXMLHTTP5.Send sBody5 
strXML5 = objXMLHTTP5.ResponseText
Response.Write("RESPONSE STATUS: " & objXMLHTTP5.status & " RESPONSE STATUS TEXT: " & objXMLHTTP5.statusText )
Response.Write("<br>" & Server.HTMLEncode(strXML5))

Set objXMLHTTP5 = Nothing
Response.Write("<br><br>")
%>
 
Notes:

1. If you wish to watch the http requests using fiddler, just convert the code
    portion you need to JavaScript. For proxy reasons fiddler will not show the http request
    for you server side calls.

2. Notice the last call to the service, finding out how to invoke a POST request and
finding  the xml format needed was hard.
Notice that the call for Person2 (which is mapped to GetDTO2) does a post request as well,
what looking at fiddler , the data is transmitted in the query string and not in the request
body, this is why i create the last call to Person4

3. You need to take special care on the order in wich you send the arguments to the WCF operations. You can use the Order property on the DataMember Attribute in the WCF composite type.

4. If you look at the following figure you will notice no soap is being send here.

image

 
Posted: Dec 07 2008, 05:23 AM by Pini Dayan | with 7 comment(s) |
תגים:,