Sunday, November 29, 2009

\m/\m/ Amon Amarth @ Bangalore

Atlast Amon amarth has set foot in India. This must be one of the most highly awaited Metal gigs in India. Adding to that excitement is my attendance.Lol.. Viking metal rulez!!And these are the gods of viking metal. If everything falls into place, i'll be at bangalore to attend the show. 5 days to go!!

Monday, November 23, 2009

At last i have my three medals in social msdn wcf forum

It feels great to have earned three medals in the msdn wcf forum. I am in the group of illustrious guys like Yaron naveh. I didnt mean to say that i am in the same league as Yaron. Hope nobody misinterprets this. He is a web services interoperability guru! I am still learning the technology everyday. But more importantly it feels great when somebody marks your answer. Yes it gives me 10 points :D. But the satisfaction derived out of the fact that you helped somebody today can be overwhelming. Hope this is a precursor for things to come.

Sunday, November 22, 2009

Single Winform Application

We wrote a production windows forms application. The requirement was that there can be only one instance of the application at any point in time. So we used Process.GetProcessByName as we knew the application name. We ran into the following problems :

1.)We didnt realize that there can be many processes with the same name. This can attributed to improper testing.
2.)Also GetProcessByName method needs admin access to execute.
3.)This is very costly method.

So what did we do?Use a named mutex. That too the name of the mutex that we chose had a GUID.If the application can acquire the named mutex with WaitOne, then it is the first instance running. If the application calls WaitOne and WaitOne returns false, another instance of the application is running and this one needs to exit.

This is what we did :


static class Program
    {

        private static string appGuid = new Guid().ToString();

        ///
        /// The main entry point for the application.
        ///

        [STAThread]
        static void Main()
        {
           
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Mutex mutex = new Mutex(false, appGuid);
            if (!mutex.WaitOne(0, false))
            {
                MessageBox.Show("Instance of applicationame is already running");
                return;
            }
            Application.Run(new Form1());
        }

Everything was good, until we deployed this in production. We were still able to create multiple instances but not as frequently as were able to do without the mutex. I am still trying to find out the reason behind this. So if anybody comes across this blog and has an answer to the above quetion please let me know.

We were able to solve the issue by keeping the mutex alive and disposing it off just before the application exits.

using (Mutex mutex = new Mutex(false, appGuid))
            {
                if (!mutex.WaitOne(0, false))
                {
                    MessageBox.Show("Instance already running");
                    return;
                }
                Application.Run(new Form1());
            }

Note that this is a local mutex and restricts creation of instances within the particular user session. To create a global mutex and make sure that there is only one instance across user sessions mutex needs to be created as following
using (Mutex mutex = new Mutex(false, @"Global\" + appGuid))

Wednesday, November 4, 2009

Reflection and Explicitly implemented interface members

I have an interface ISomeInterface that does something.

public interface ISomeInterface
{
void DoSomething();
}

And a class SomeClass that implements ISomeInterface explicitly.

public class SomeClass : ISomeInterface
{
#region ISomeInterface Members

void ISomeInterface.DoSomething()
{
throw new NotImplementedException();
}

#endregion
}

My goal was to reflect the members of SomeClass. So i went ahead and wrote this common code :

Type type = typeof(SomeClass);
MethodInfo[] methodInfo = type.GetMethods();

To my surprise methodInfo had only those methods provided by System.Object.



Hold on where's my interface method? Taking a second look at my SomeClass i found that explicitly implemented member was private to SomeClass. Ok So this brings BindingFlags into play. BindingFlags control the binding and specify the way search is conducted for types and members in reflection. Luckly GOOGLE did the trick again.

Type type = typeof(SomeClass);


MethodInfo[] methodInfo = type.GetMethods(BindingFlags.NonPublic
BindingFlags.Instance);


Collection already contains an address with scheme http

This summary is not available. Please click here to view the post.

Sunday, November 1, 2009

Hosting WCF Service in Windows forms application and Sendtimeout exception

I was entrusted with a development of a POC(proof of concept) for an occasionally connected service. The client was a smart client application and the service was written in WCF. The idea was to have a online service when the machine was connected to a network and to use a self hosted service when not connected to the network. The sync between online and offline data would be take care by ado.net sync services.

The idea was to host the service in the shell form. If you know or heard about CAB SCSF then you are sure to know about shell form. Right so i have my offline service implementation and the contracts were in an assembly to enable re use between offline and online services.

This is what i did to host my service

public Form1()
{
InitializeComponent();
ServiceHost host = new ServiceHost(typeof(Service1));
host.Open();

}
I hosted my service in the form's constructor. I called my service operation in the form_load event

ChannelFactory factory = new ChannelFactory(new WSHttpBinding(), new EndpointAddress("http://localhost:8731/Design_Time_Addresses/WindowsFormsHost/Service1/"));
IService1 proxy = factory.CreateChannel();
proxy.DoWork();

This is the exception i got

Photobucket

Seems quite wierd. After hosting it in the current winform i tried accesing it from another winform solution and i was able to access the service. Ok so, i was hosting the service in proc which failed. So my service is fine.

I was able to nail the problem after a long tiresome googlejob!! The more I looked the more it became painfully obvious that I had a threading deadlock issue. The UseSynchronizationContext from the ServiceBehavior attribute in WCF is used to determine which thread your service will execute on. Basically System.Threading.SynchronizationContext.Current is read and cached so that when a request comes to the service, the host can marshal the request onto the thread that the host was created on using the cached SynchronizationContext.

As i mentioned earlier the timeout exception was due to a deadlock. The reason for this is that the default value of the UseSynchronizationContext is true and so when you create the ServiceHost on the UI thread of the winform application, then the current synchronization context is a DispatcherSynchronizationContext which holds a reference to a System.Windows.Threading.Dispatcher object which then holds a reference to the current thread. The DispatcherSynchronizationContext will then be used when a request comes in to marshal requests onto the UI thread. But if you are calling the service from the UI thread then you have a deadlock when it tries to do this!!

Phew!!! There are two ways to fix this issue.

1.)First one is to declare [CallbackBehavior(UseSynchronizationContext = false)] on the service class. Set that to false on your service and the service will create it's own SynchronizationContext and your client will no longer block when hosting the service in process.

2.)Host the servie before form constructor is invoked.

[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
ServiceHost host = new ServiceHost(typeof(Service1));
host.Open();

Application.Run(new Form1());
}

Monday, October 26, 2009

Flowing ASP.NET Forms authentication cookie to WCF

This being my first blog,I would like to start off with something that I love. WCF!!!This is about flowing ASP.NET Forms authentication to WCF service. Once successfully authenticated, forms authentication data is stored as an encrypted cookie. And since the encryption is machine dependent its important to have the validationKey and decryptionKey same in both the web.configs(web app and WCF app).

Check this MSDN link to know more about configuring machineKey for asp.net forms authentication.

1.)Create a validationkey and decryptionkey. Run the below program two times. The value generated first time can be used as the validationKey and the second one machineKey in the web.configs.

static void Main(string[] args)
{
int len = 48;

byte[] buff = new byte[len / 2];
RNGCryptoServiceProvider rng = new
RNGCryptoServiceProvider();
rng.GetBytes(buff);
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < buff.Length; i++)
sb.Append(string.Format("{0:X2}", buff[i]));
Console.WriteLine(sb);

}

2.)Configure the web.configs(wcf and web app) to use the generated keys as follows.

<system.web/>
<span style="font-weight:bold;"/> <machineKey validationKey="D4E763ABFD89DAAD50620E89E11FFAB7AD94AF9EDE264526" decryptionKey="5F0A4D7396E35CF534F0B404F481CA70C2C5A43071729BE4" decryption="3DES"/>
</span>

3.)Configure the WCF service to run in ASP NET compatibility mode.
This is to be done in two place. One in wcf service web.config as follows

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

And

in the service behaviour
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{

4.)Configure forms authentication in asp.net config

<authentication mode="Forms">
<forms name="appNameAuth" path="/" loginUrl="login.aspx" protection="All" timeout="30">
<credentials passwordFormat="Clear">
<user name="jeff" password="test" />
<user name="mike" password="test" />
</credentials>
</forms>
</authentication>
<authorization>
<deny users="?" />
</authorization>
5.)In login.aspx

if (FormsAuthentication.Authenticate(txtUser.Text, txtPassword.Text))
FormsAuthentication.RedirectFromLoginPage(txtUser.Text, chkPersistLogin.Checked);
else
ErrorMessage.InnerHtml = "Something went wrong... please re-enter your credentials...";
This sets the authentication cookie on successful login.

6.)Now send the cookie in WCF request http header

HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers.Add(HttpRequestHeader.Cookie, FormsAuthentication.GetAuthCookie(User.Identity.Name, false).Value);

ServiceReference1.Service1Client serviceClient = new WebApplication1.ServiceReference1.Service1Client();

using (OperationContextScope scope = new OperationContextScope(serviceClient.InnerChannel))
{
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
string s =serviceClient.GetData(2);
}

7.)At the service side you can read the cookie inside the operation as follows

HttpRequestMessageProperty g = OperationContext.Current.IncomingMessageProperties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
string s = g.Headers.Get(HttpRequestHeader.Cookie.ToString());
FormsAuthenticationTicket tick = FormsAuthentication.Decrypt(s);


Working sample can be downloaded from here

Let me know on any issues. Happy coding :)