Saturday, August 11, 2012

How to retrieve service metadata for WCF services that use X509 certificates for client validation


Svcutil is wonderful tool and it comes handy when trying to create WCF client applications. It makes use of the MEX endpoint and retrieves the config and proxy classes.  

Where to look for svcutil.exe tool and its configuration in your machine (WIN 7 64bit):
 C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin
[select the right version "v7.0A"]

In Visual studio command shell, you can type as follows
Svcutil http://MyTestService/Test.svc

This will generate the service endpoint information as config and proxy as a .cs file.

This approach does not work for the WCF services that demands client authentication certificate while receiving the actual or metadata-exchange request. 

You may have kept the client authentication certificate in your “localmachine” or “currentuser” certificate store (mostly in “personal”) [You can do this either via MMC console or certification manager tool]

In such cases if you try to execute this tool you will be receiving error as below
-------------------------------------------------------------------------
WS-Metadata Exchange Error
URI: https://MyTestService/Test.svc
Metadata contains a reference that cannot be resolved: 'https://MyTestService/Test.svc'.
The HTTP request was forbidden with client authentication scheme 'Anonymous'
The remote server returned an error: (403) Forbidden.
-------------------------------------------------------------------------
This happens as the svcutil does not know where to look for the certificate. There is an easy way to get this working
  1.      Locate the svcutil.exe and svcutil.exe.config
  2.     Copy it to any of your folder let’s say c:\temp\
  3.     Now modify the svcutil.exe.config to have the corresponding certificate store information (mention specific endpoint details and client credentials) 

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <client>
      <endpoint behaviorConfiguration="wsHttpBehavior"
         binding="wsHttpBinding" bindingConfiguration="wsHttpMex"
         contract="IMetadataExchange" name="https"/>
    </client>
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttpMex">
          <security mode="Transport">
            <transport clientCredentialType="Certificate" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="wsHttpBehavior">
          <clientCredentials>
                  <clientCertificate findValue="<clientcertificatesubject>"
                  storeLocation="LocalMachine"
                  storeName="My"
                  x509FindType="FindBySubjectName" />          
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>
4.  Now the following command will be working as the svcutil is now able to locate the certificate in LocalMachine\Personal certificate store.


Tuesday, April 3, 2012

Solving the ViewState code cluttering in ASP.net Web Forms

If you have worked on asp.net forms then you would have noticed the issue with viewstate from a maintenance point of view.  If we need to temporarily keep a value during post backs then one of the ways to do it is to store into page or control viewstate. Most of the rush jobs will introduce viewstate with magic strings (e.g. ViewState[“TestId”]) through out the page and soon you will see the a maintenance monster getting ready to overpower you. One of the ways to isolate this problem is to re-factor this code (view state magic strings) to properties.By this technique of limiting viewstate usage to a property we can achieve type safety and localize the issue.

But the code might look like this and its a good start as this approach gives some type safety.
     public long TestId
        {
            get
            {
                if (ViewState["TestId"] != null)
                {
                    return System.Convert.ToInt64(ViewState["TestId"]);
                }
                else
                {
                    return 0;
                }
            }
            set
            {
                ViewState["TestId"] = value;
            }
        }

While looking at a nicer way to solve this issue i came across with a code project blog which talks about creating reusable attributes.By applying this attribute based programming model we will be able to push data onto viewstate in a much clean way as below.

// new way of defining a viewstate property will be
[ViewStateProperty]
public long TestId { get; set; }

Though the real inspiration is from the above mentioned article, some customizations are done to support the generic use and explained implementation details in the following 5 steps.

Step 1. Define IViewStateProperty interface which can later provide extensibility and scoping (only those user control marked with this interface will have the feature of ViewStateProperty attribute)
 public interface IViewStateProperty    {    }

Step 2. Define ViewStateProperty attribute
   [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
    public class ViewStateProperty : Attribute
    {
        public string ViewStateName { get; private set; }
        public object DefaultValue { get; set; }

        public ViewStateProperty()
        {
            this.ViewStateName = string.Empty;
        }

        public ViewStateProperty(object defaultValue)
        {
            this.DefaultValue = defaultValue;
        }
    }  

Step 3. Define ViewStatePageBase Custom UI Page Base class
/// <summary>/// DEVNOTE: ViewStateProperty instances that are declared as 'private' may not //// be found on reflection (if the application is running in medium trust. E.g. /// when you are running on a shared hosting environment)/// </summary>
  public class ViewStatePageBase : System.Web.UI.Page
    {
        protected override void OnPreLoad(EventArgs e)
        {
            base.OnPreLoad(e);

            this.DoLoadViewStateProperties(this);
            this.LoadViewStatePropertiesRecursive(this.Controls);
        }

        protected override void OnPreRenderComplete(EventArgs e)
        {
            base.OnPreRenderComplete(e);

            this.DoSaveViewStateProperties(this);
            this.SaveViewStatePropertiesRecursive(this.Controls);
        }

        private void LoadViewStatePropertiesRecursive(ControlCollection controls)
        {
            foreach (Control ctrl in controls)
            {
                if (ctrl is IViewStateProperty)
                {
                    this.DoLoadViewStateProperties(ctrl);
                }
                LoadViewStatePropertiesRecursive(ctrl.Controls);
            }
        }

        private void SaveViewStatePropertiesRecursive(ControlCollection controls)
        {
            foreach (Control ctrl in controls)
            {
                if (ctrl is IViewStateProperty)
                {
                    this.DoSaveViewStateProperties(ctrl);
                }
                this.SaveViewStatePropertiesRecursive(ctrl.Controls);
            }
        }

        private void DoLoadViewStateProperties(Control ctrl)
        {
            var properties = ctrl.GetType().GetProperties(BindingFlags.Public 
                           | BindingFlags.NonPublic | BindingFlags.Instance)
                .Where(prop => Attribute.IsDefined(prop, typeof(ViewStateProperty), true))
                .Select(p => new ViewStatePropertyInfo()
                {
                    ViewStateName = ((ViewStatePropertyp.GetCustomAttributes (typeof(ViewStateProperty), true)
                                             .FirstOrDefault()).ViewStateName,
                    PropertyInfo = p
                });

            foreach (var property in properties)
            {
                var localName = String.Format("{0}_{1}"
                                                , ctrl.ClientID
                                                , String.IsNullOrEmpty(property.ViewStateName)
                                                    ? property.PropertyInfo.Name
                                                    : property.ViewStateName); 
                if (ViewState[localName] != null)
                {
                    property.PropertyInfo.SetValue(ctrl, ViewState[localName], null);
                }
            }
        }

        private void DoSaveViewStateProperties(Control ctrl)
        {
            var properties = ctrl.GetType().GetProperties(BindingFlags.Public 
                                        | BindingFlags.NonPublic | BindingFlags.Instance)
                .Where(prop => Attribute.IsDefined(prop, typeof(ViewStateProperty), true))
                .Select(p => new ViewStatePropertyInfo()
                {
                    ViewStateName = ((ViewStateProperty)p.GetCustomAttributes(typeof(ViewStateProperty), true)
                                         .FirstOrDefault()).ViewStateName,
                    PropertyInfo = p
                });

            foreach (var property in properties)
            {
                var localName = String.Format("{0}_{1}"
                                                , ctrl.ClientID
                                                , String.IsNullOrEmpty(property.ViewStateName)
                                                    ? property.PropertyInfo.Name
                                                    : property.ViewStateName);
                ViewState[localName] = property.PropertyInfo.GetValue(ctrl, null);
            }
        }

        private struct ViewStatePropertyInfo
        {
            internal string ViewStateName { get; set; }
            internal PropertyInfo PropertyInfo { get; set; }
        }
    }
Step 4. Apply layer super type pattern to pages (aspx.cs) and ensure they inherit from custom base class (ViewStatePageBase) instead of System.Web.UI.Page.
e.g. A Test Page will inherit from a custom ViestatePageBase as follows
public partial class TestPage : ViewStatePageBase

Step 5. To bring user controls to this equation try inheriting from a base class (UserControlBase) and implement with the IViewStateProperty  

public class UserControlBase : System.Web.UI.UserControl, IViewStateProperty

i.e. TestUserControl.ascx.cs will be as defined follows
public class TestUserControl : UserControlBase

Now you are all set to decorate properties with [ViewStateProperty] attribute and use code as below
[ViewStateProperty]
public long TestId { getset; }

Saturday, February 11, 2012

Quick tip to fix Cache Control issue with IE 8

There are instances where you want the page cache to say get out of my way and let me go to the server. One such instance would be when you are trying to create a PDF document out of a page response.  It’s quite common to leave the HttpCacheability property alone or in some instances set the property to "Server" or “ServerAndNoCache”) to get optimum performance.


If the page is going to be extremely dynamic as the pdf generation case mentioned above, then you are left with no choice other than setting the  HttpCacheability to NoCache.  The general syntax is as follows

Response.Cache.SetCacheability(HttpCacheability.NoCache)

This way of setting the cache control header will not work properly for IE 8 (and some older browsers).  So the following old fashioned syntax is respected by all the browsers including the IE brothers.

Response.AddHeader("Cache-Control", " no-store, no-cache ");