16 December 2008

[Serializable] does not inherit (aka RTFM)

Of course, everybody knows that if you want to serialize an object, you need to decorate the class with the [Serializable] attribute. Right? Well, yes, and so do I, but I ran into a snag today: it is an attribute, not a property so it does not inherit. If you consider the following code
using System;

namespace demo
{
    [Serializable]
    public class BaseClass
    {
        public string AProperty { get; set; }
    }

    public class ChildClass : BaseClass
    {
        public string AnotherProperty { get; set; }
    }
}
you will find that Childclass will not serialize with BinaryFormatter, although its base class will. This is of course quite evident, but a more interesting gotcha occurs when you add a third class:
    [Serializable]
    public class ChildClass2 : ChildClass
    {
        public string FinalProperty { get; set; }
    }
This won't serialize either, because halfway up it's class hierarchy there's a non-serializable class. In plain vanilla .NET this will generate an "Failed to serialize. Reason: Type 'demo.ChildClass' in Assembly 'bla bla bla' is not marked as serializable", precisely pinpointing the problem. If it happens (as in my case) deep down inside a CSLA dataportal, all you get is an error message like
System.ServiceModel.CommunicationException: The underlying connection was closed: The connection was closed unexpectedly. ---> System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly.
And you might spend quite some time finding out it is caused by a non-serializable class somewhere in your class hierarchy. So, check your attributes, folkes ;-) Or run FxCop (and read the warnings)

12 December 2008

Calling Oracle stored functions from ADO.NET

Die-hard Microsofties may be flabbergasted, but there are people out there using Oracle as a database in stead of SQLServer and - oh horror - are even daft enough to try to retrieve data from it using ADO.NET. But while Microsoft cranks out code samples for using SQLServer by the the truckload, those that are living in a hybrid environment may have a hard time finding actual working data access sample code. Like calling a stored function in Oracle and retrieving the value. Suppose whe have the following trivial stored function, created by my collegue Louis Ywema for unit testing purposes. It takes a numerical value and a string value and concatenates them with a hyphen between. Not quite the functionality you've been waiting for all your life but it proves the point
create function get_test  (p_parameter1 in number
                   ,p_parameter2 in varchar2)
return varchar2
is
   l_parameter1 number;
   l_parameter2 varchar2(1024);
begin
   l_parameter1 := p_parameter1;
   l_parameter2 := p_parameter2;
   return to_char(l_parameter1)||' - '||l_parameter2;
exception
   when others then
       return(sqlerrm);       
end get_test
You run this code in a database user that has CREATE PROCEDURE privileges Next, you define an Oracle connection in your connectionStrings section of your config file:
<connectionStrings>
  <add name="MYCONNECTION" 
    connectionString="Password=TEST;User ID=TEST;Data Source=JOOST;"
    providerName="System.Data.OracleClient" />
</connectionStrings>
I use a database JOOST with username TEST and password TEST Using raw ADO.NET code you can run the stored function like this
[TestFixture]
[Test(Description = "Stored function - Raw ADO.NET")]
public void TestStoredFunctionRaw()
{
  var myConnection = 
      ConfigurationManager.ConnectionStrings["MYCONNECTION"];
  using (var connection = 
      new OracleConnection(myConnection.ConnectionString))
  {
     connection.Open();
     using(var command = connection.CreateCommand() )
     {
       var p1 = new OracleParameter("p_parameter1", OracleType.Number);
       p1.Value = 1;
       command.Parameters.Add(p1);

       var p2 = new OracleParameter("p_parameter2", OracleType.VarChar);
       p2.Value = "Hello";
       command.Parameters.Add(p2);

       var retVal = new OracleParameter("returnvalue", OracleType.VarChar);
       retVal.Size = 1024;
       retVal.Direction = ParameterDirection.ReturnValue;
       command.Parameters.Add(retVal);

       command.CommandText = "get_test";
       command.CommandType = CommandType.StoredProcedure;
       command.ExecuteNonQuery();

       Assert.IsTrue(((string)retVal.Value) == "1 - Hello");
     }
  }
}
I would not recommend this to anyone but it proves the point. For real life situations, use the Enterprise Library and write your code like this
[Test(Description = "Stored function -  EL")]
public void TestStoredFunctionEntLib()
{
    Database Db = DatabaseFactory.CreateDatabase("MYCONNECTION");
    using (var cmd = Db.GetSqlStringCommand("get_test" ) )
    {
      Db.AddInParameter(cmd, "p_parameter1", DbType.VarNumeric, 1);
      Db.AddInParameter(cmd, "p_parameter2", DbType.String, "Hello");
      Db.AddParameter(cmd, "returnvalue", DbType.String,1024, 
        ParameterDirection.ReturnValue, 
        false, 0, 0, null, DataRowVersion.Default, null);

      cmd.CommandType = CommandType.StoredProcedure;
      Db.ExecuteNonQuery(cmd);
      Assert.IsTrue(((string) cmd.Parameters[2].Value) == "1 - Hello");
    }
}
Notice the "returnvalue" parameter - it has a ParameterDirection.ReturnValue and more importantly - it has a size. This is important: the default size of a parameter is 0, and if Oracle tries to write back te parameter value into the parameter you will get an error indicating so. In this example I use 1024, but you can set this to any size you need. In my production code I set it to 32K (32768) but I am not sure of the absolute maximum value. The crazy thing about this is, of course, there are situations where you cannot know the size of the return value. Your only option is to set is as high pas possible and hope for the best ;-) Complete test project downloadable here. This example still uses the May 2007 EntLib 3.1, by the way.

04 December 2008

Converting colors from RGB to HTML and back

A very short one this time: it turns out to be pretty easy to convert a RGB color to a HTML color and back. This may come handy when (like me) you are using configuration files in which colors for map features are specified in RGB. Add a reference to System.Drawing.dll and a "using System.Drawing" to your class and you can use the following code:
Color rgbColor = Color.FromArgb(255, 0, 0);
string HTMLColor = ColorTranslator.ToHtml(rgbColor);
Color rgbColor2 = ColorTranslator.FromHtml(HTMLColor);
Color rgbColor3 = ColorTranslator.FromHtml("Fuchsia");

 Console.WriteLine(HTMLColor);
 Console.WriteLine(string.Format("{0},{1},{2}",
     rgbColor2.R, rgbColor2.G, rgbColor2.B));
 Console.WriteLine(string.Format("{0},{1},{2}",
     rgbColor3.R, rgbColor3.G, rgbColor3.B));
this wil output the following: #FF0000 255,0,0 255,0,255 I translated RGB red to HTML red, and back. For an encore, I demonstrated the fact that named colors are translated into RGB as well.

29 November 2008

Writing a simple HTTP proxy using WCF

I ran into a situation with the following network topology: The intranet server served PDF documents via IIS, but was only accessible from the WCF server - which, for technical and political reasons, could not run in IIS but had to be a Windows Managed service that hosted a WCF service. Yet I needed to be able to download files from the intranet server via an ordinary URL. It turns out that you can write a WCF service mimicking a HTTP server pretty easily. If you can utilize .NET 3.5SP1, that is. 1. Data contract There are few key points to the contract:
  • Make a reference to System.ServiceModel.Web.dll
  • Add a "using System.ServiceModel.Web"
  • Define a method returning a Stream
  • Decorate that method with a WebGet attribute
Your datacontract could look like this:
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace ProxyService
{
    /// 
    /// Service contract for a proxy that forwards a http request
    [ServiceContract]
    public interface IHttpProxy
    {
        [OperationContract, WebGet]
        Stream GetProxyRequest(string target);
    }
}
2. Implementation class This is basically a modified version of a solution based upon an ASP.NET page I described before.
using System.IO;
using System.Net;
using System.ServiceModel.Web;
using System.Web;

namespace ProxyService
{
    /// 
    /// A proxy that forwards a http request
    /// 
    public class HttpProxy : IHttpProxy
    {
        public Stream GetProxyRequest(string target)
        {
            var urlToLoadFrom = HttpUtility.UrlDecode(target);
            HttpWebRequest webRequest = 
               HttpWebRequest.Create(urlToLoadFrom) as HttpWebRequest;

            // Important! Keeps the request from blocking after the first
            // time!
            webRequest.KeepAlive = false;
            webRequest.Credentials = CredentialCache.DefaultCredentials;
            using (var backendResponse = 
              (HttpWebResponse)webRequest.GetResponse())
            {
                using (var receiveStream = 
                  backendResponse.GetResponseStream())
                {
                    var ms = new MemoryStream();
                    var response = 
                      WebOperationContext.Current.OutgoingResponse;
                    // Copy headers
                    // Check if header contains a contenth-lenght since IE
                    // goes bananas if this is missing
                    bool contentLenghtFound = false;
                    foreach (string header in backendResponse.Headers)
                    {
                        if (string.Compare(header, 
                          "CONTENT-LENGTH", true) == 0)
                        { 
                          contentLenghtFound = true;
                        }
                        response.Headers.Add(header, 
                          backendResponse.Headers[header]);
                    }

                    // Copy contents
                    var buff = new byte[1024];
                    var length = 0;
                    int bytes;
                    while ((bytes = receiveStream.Read(buff, 0, 1024)) > 0)
                    {
                        length += bytes;
                        ms.Write(buff, 0, bytes);
                    }

                    // Add contentlength if it is missing
                    if (!contentLenghtFound) response.ContentLength = length;

                    // Set the stream to the start
                    ms.Position = 0;
                    return ms;
                }
            }
        }
    }
}
3. Configuration settings To get it all to work, you will need some configuration settings in the App.config of the hosting application:
<system.serviceModel>
  <services>
    <service name="ProxyService.HttpProxy" >
      <endpoint address="" binding="webHttpBinding"
                behaviorConfiguration="WebHttpBehavior"
                contract="ProxyService.IHttpProxy" >
      </endpoint>

      <host>
        <baseAddresses>
          <add baseAddress="http://localhost:8002/ProxyService.HttpProxy" />
        </baseAddresses>
      </host>
    </service>

  </services>
  <behaviors>
    <endpointBehaviors>
      <behavior name="WebHttpBehavior">
        <webHttp />
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>
Notice the endpointBehaviors section: this is really important to get the stuff to work. 4. Using the proxy You can now simply enter "http://yourhost:8002/ProxyService.HttpProxy/GetProxyRequest?target=urlencodedurl" in your browser, and the WebGet attributes will automatically make the GetProxyRequest method get called with the value of target as value for the target parameter. The code of the proxy expects target to contain an URLEncoded URL (use HttpUtility.UrlEncode to encode the actual url to something that can be passed as a parameter on an URL). Concluding remarks The magic of the WebGet attribute is barely scratched by this example, but it makes creating REST services with WCF a real piece of cake. I am not sure if it was intended to be used this way, but it sure works like hell ;-)

20 October 2008

Turning off WCF security

Unlike ye goode ole ASMX web services, WCF comes by default with security enabled. That's a good thing: Microsoft now believes in security being integral part of the solution, so in stead of slapping it on later, it is turned on by default. This is fine of course in distributed production environments but may be a real PITA while testing or deploying in a simple point-to-point enviroment, especially when machines are not in the same domain. Fortunately, turning all these gizmos off is quite easy. The catch is that settings on server and client must exactly match You host the service like this (provided it is hosted in IIS)
<system.serviceModel>
  <services>
    <service name="MyService">
      <endpoint contract="IMyService" binding="wsHttpBinding" bindingConfiguration="wsHttpBindingConfiguration"/>
    </service>
  </services>
  <bindings>
    <wsHttpBinding>
      <binding name="wsHttpBindingConfiguration">
       <security mode="None">
          <message clientCredentialType="None"/>
          <transport clientCredentialType="None"/>
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
</system.serviceModel>
and you configure the client like this
<system.serviceModel>
  <client>
    <endpoint name="MyDataPortal"
              address="http://someserver:2000/MyRoot/MyService.svc"
              binding="wsHttpBinding"
              contract="IMyService"
              bindingConfiguration="MyBinding"/>
  </client>

  <bindings>
    <wsHttpBinding>
      <binding name="MyBinding">
        <security mode="None">
          <message clientCredentialType="None"/>
          <transport clientCredentialType="None"/>
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
</system.serviceModel>
I emphasized the important parts. Be advised: these settings should only be used in either development environments or enviroments that are inherently safe by themselves, i.e. closed networks.

25 July 2008

Shared code development and easy unit testing with Compact Framework

Microsoft made developing for the Compact Framework relatively easy. Everyone with experience in .NET development can easily take the plunge into mobile development by downloading the Windows Mobile SDK 6.x and go on as if you are just working in the full framework. You will notice some restrictions, not everything you might want to use is available, programs running on mobile device face some very specific challenges, but then again, the development experience is quite seamless.

Some things remain a bit cumbersome. Unit testing can be a real PITA, and you cannot binary reuse code, so if your shop (like mine) uses some utilities that are distributed as binary components, they will have to be recompiled specifically for the Compact Framework and someone has to keep the CF and Full version in sync.

Fortunately Visual Studio sports an almost hidden feature that can make life a lot easier for Mobile developers. The following procedure assumes that you have Visual Studio 2008 professional edition and the Windows mobile 6 SDK installed. For unit testing I use NUnit and Testdriven.NET to launch it from Visual Studio, but you can of course use anything you like

1. Make a new empty solution
Let's call it "SharedCode"

2. Add a new Smart Device application
Select Add/new project/Smart Device
Use "MyMobileApp" as name
Select Smart Device, Windows Mobile 6.0 professional SDK, and Compact Framework 3.5 although for this sample only the first option is really important.

3. Add another Smart Device application
Select Add/new project/Smart Device
Use "MyMobileLib" as name
Select Class Library, Windows Mobile 6.0 professional SDK, and Compact Framework 3.5

4. Add two Windows Class library projects
These must be full framework projects, not mobile projects.
Call the first one "MyLib" and the second one "MyLib.Test". Select .NET framework 3.5 as target framework

5. Add a new class to the MyMobileLib assembly
For this example, we will use a trivial calculator class:
namespace MyMobileLib
{
public class Calculator
{
private int Num1;
private int Num2;

public Calculator(int num1, int num2)
{
Num1 = num1;
Num2 = num2;
}

public int Add()
{
return Num1 + Num2;
}

public int Subtract()
{
return Num1 - Num2;
}
}
}

6. Add as link to the MyLib library
Go to the MyLib library and remove the default generated "Class1.cs" file.
Then right-click the project and select "Add/Existing Item".
And now for the piece the resistance:
Browse one directory up, then down into the MyMobileLib directory, and select the Calculator.cs file.
Now look carefully to the "Add" button down right. It will sport a hard-to-spot small arrow pointing downwards:
If you click that, you will get two options: Add and Add as link. That is what I mean by "an almost hidden feature". Select "Add as link" and you will see that "Calculator.cs" is added to the MyLib project, but that the document icon has a shortcut arrow overlay:







7. Add references
Right-click the MyMobileApp project
Select "Add Reference", click Tab "projects" and select the "MyMobileLib" project

Right-click the MyLib.Test project
Select "Add Reference", click Tab "projects" and select the "MyLib" project

8. Define unit test in de MyLib.Test project
Rename the default Class.cs file in MyLib.Test to "TestCalculator.cs".
Since I use NUnit, I have to make a reference to the nunit.framework.dll which sits somewhere on my system. Then I can create the world shocking ;-) test
using MyMobileLib;
using NUnit.Framework;

namespace MyLib.Test
{
[TestFixture]
public class TestCalculator
{
[Test]
public void TestCalc1()
{
Calculator c = new Calculator(3,2);
Assert.AreEqual(5, c.Add());
Assert.AreEqual(1, c.Subtract());
}
}
}
which will undoubtly work. But my point is: you can simply run units tests out of the Windows Mobile scope, inside Visual Studio

9. Test the library on the mobile device
For the sake of brevity: drag a label onto the form.
Open the Form1.cs, and add to the code on the form:
using System.Windows.Forms;
using MyMobileLib;

namespace MyMobileApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Calculator c = new Calculator(3, 2);
label1.Text = "3 + 2 = " + c.Add()
;
}
}
}
If you run this, open pops the Windows Mobile emulator and the form will show the 'surprising' message "3 + 2 = 5".

Conclusion
While the sample was trivial, it showed two things:
  • For general purpose classes, you can develop code and generate binaries for both Compact and full framework using a single code file

  • Unit testing of general purposes classes can be done outside a Windows Mobile emulator and becomes a lot easier this way



Complete code downloadable here.

23 May 2008

Don't ever use backslashes in Silverlight 2 image URLS!

I had a great time today and yesterday at the Microsoft Developer Days 2008 in Amsterdam, where they shared quite a bit of data on Silverlight 2.0. I have been hacking along with it for some time now and I would like to share a bit of hard-won information I stumbled across. That piece of information is quite simple: If you programmatically set an URL to an Image, do not ever let the URL contain a backslash, not even when it is URLEncoded So, suppose your XAML looks like this:
<usercontrol class="SilverMapLoader.Page" 
  xmlns="http://schemas.microsoft.com/client/2007" 
  x="http://schemas.microsoft.com/winfx/2006/xaml" 
  width="700" height="500">
  <canvas name="LayoutRoot" background="Gray">
    <img height="460" src="" width="700" name="map" top="0" left="0" />
  </img>
  </canvas>
</usercontrol>
You can set the URL to the image in your Page.xaml.cs like this:
string URL = "http://www.someadress.org/image.jpg";
map.Source = new System.Windows.Media.Imaging.BitmapImage(new Uri(URL));
Now I was trying to show images that came from some cache mechanisme that effectively needed URLs like this:
http://localhost:2872/SilverMapLoaderClient/MapLoaderCache.aspx?CacheFileData=C%3a%5cMapLoaderCache5cMapLoaderCache.png"
Silverlight simply does not show the image. It does not even give an error message. I suppose this is a bug, but this is more or less how I programmed around it:
string newURL = URL.Replace("\\", "/").Replace("%5c", "%2f").Replace("%5C", "%2F");
Effectively I am replacing all backslashes by forward slashes. And modified the page that actually loads the images so that it understands that forward slashes need to be translated into back slashes before the actual path is picked. It does not win a beauty contest, but it works, and in the end, that's all that counts It took me the better part of a rainy Saturday to find this out, while I was actually on planning on finding out a lot of Silverlight, and I reported it as a bug on Silverlight.net. Maybe this post will save some poor sod from repeating my experience ;-) Update: obviously my report helped, since I just installed SilverLight 2.0 release, upgraded and recompiled the project, deleted the workaround code, and it still works as a charm.

16 March 2008

JSON services revisited: using a Dictionary as a generic parameter

Somebody at Microsoft deserves a Nobel Prize. Well, that is maybe a bit strong, but I ran into the problem that I wanted to create JSON scriptserver that would accept a 'parameter bag' of unknown size and type. I expected problems in the serialization, since Javascript typing is at best a bit lax, but it turns out that when you define a web service with a parameter of type Dictionary<string, object> dict, the JSON serializer automatically derives the object types from the javascript data! It works like this: suppose we define the following method:
[WebMethod]
public string DictMethod(Dictionary<string, object> dict)
{
  StringBuilder b = new StringBuilder("C# reports<BR/>");
  foreach( string s in dict.Keys )
  {
    b.AppendFormat(string.Format("{0}:{1}={2}<BR/>", s, dict[s].GetType(), 
                   dict[s]));
  }
  return b.ToString();
}
We can call this method from javascript like this
<script type="text/javascript">
  function LoadDict()
  {
    dict = new Object();
    dict["test1"] = "Joost";
    dict["test2"] = 21;
    dict["test3"] = true;
    dict["test4"] = 9999999999;
    dict["test5"] = new Date(2008,09,12,13,14,00);
    DictService.DictMethod( dict, ProcessResult );
  }

  function ProcessResult( WebServiceResult )
  {
    document.write( WebServiceResult );
  }
</script>
If you attach the LoadDict javascript function to some client side event (The OnClientClick of a button for example) and launch it, you will see the following output: C# reports test1:System.String=Joost test2:System.Int32=21 test3:System.Boolean=True test4:System.Int64=9999999999 test5:System.DateTime=12-10-2008 11:14:00 So you can see, the javascript string converted into a true .NET string, the value 21 into an Int32 - but the value 9999999999 is too long for an int and is converted into a Int64, a.k.a. long - I really like that one, for it shows true craftmanship of the programmer ;-). The "true" javascript value is converted into a Boolean finally, the javascript Date is converted into a neat DateTime. And presto, all your stuff is converted into real .NET objects. Of course, you should always used typed parameters when possible, but for some generic solutions this may come in very handy. Complete code downloadable here.

08 March 2008

Running and debugging a Windows Managed Service directly from Visual Studio.NET

Developing a Windows Managed Service (i.e. a service written in .NET ;-) ) is a lot easier than it used to be, still it can be a real PITA to debug, especially in the early stages, and even more so when the service is a kind of server and something goes wrong with the communication. You are continually running in circles:
  1. Stop running service
  2. Replace binaries
  3. Start services
  4. Attach Visual Studio debugger to process
  5. Launch your client process
  6. Find bug
  7. Fix bug
  8. Repeat until no more bug.

Life could be so much easier if you could launch the service from Visual Studio and see how it behaves. And the fun thing is, you can.

1. Create a new service project in your solution
If you already have a service project you can skip this step. I'll add a service project DemoService with a Service MyService in it with not too complicated functionality:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;

namespace DemoService
{
  public partial class MyService : ServiceBase
  {
    public MyService()
    {
      InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
      Console.WriteLine("OnStart");
    }

    protected override void OnStop()
    {
      Console.WriteLine("OnEnd");
    }
  }
}

2. Change the application output type
Right-click the DemoService project, choose "Properties", click tab "Application". Default this says "Windows application" - change this to Console application

3. Add debug mode methods to your service class

#if DEBUG

  public void StartService()
  {
   OnStart(null);
   Console.WriteLine("MyService started, press >ENTER< to terminate");
   Console.ReadLine();
  }

  public void StopService()
  {
   OnStop();
  }
#endif
4. Add debug mode code to the Main method
Open the "Program.cs" file in the service project, and change it so it looks like this
using System;
using System.Collections.Generic;
using System.ServiceProcess;
using System.Text;

namespace DemoService
{
  static class Program
  {
    /// 
    /// The main entry point for the application.
    /// 
    static void Main()
    {
#if DEBUG
      MyService s = new MyService();
      s.StartService();
      s.StopService();

#else
      ServiceBase[] ServicesToRun;

      ServicesToRun = new ServiceBase[] { new MyService() };

      ServiceBase.Run(ServicesToRun);
#endif
    }
  }
}

And that's it. You can now run the 'service' as a program in debug mode - it will pop-up a console window in which the 'service' runs and says OnStart MyService started, press >ENTER< to terminate

If you hit enter, you will just be able to see "OnEnd" passing by before the window closes. Of course, normally you will launch a thread of some kind in the OnStart method, or you will start a WCF service, and then you can see the dynamic behaviour of the 'service' while it runs by adding more "Console.WriteLine" calls - or, since it is already a process inside VS.NET, see it hit breakpoints or the exception you have been hunting all week now. And by setting the solution to "Multiple Startup" you can start both 'service' and client in one go.

And if you make a release build, all this stuff will be left out and the service will be compiled as a proper service which can be installed and will run in the usual way.

CAVEAT: be aware that the 'service' is running with your login credentials when it runs in a console window, and not as 'System'. This method is therefore not applicable when debugging access releated problems.

04 March 2008

Simplyfying refactoring by making things obsolete

A very simple one I ran into today - when you are refactoring things, sometimes old methods are no longer required, but for the sake of backward compatiblity your want to retain them. To make sure your own code no longer calls the deprecated method, simply use the ObsoleteAttribute:
[ObsoleteAttribute("Warning you want the compiler to give")]
public void ObsoleteMethod()
{
  // ....
}
If you now recompile your program, every call to ObsoleteMethod displays the message "Warning you want the compiler to give" in the output window - you might want to change that message to something more useful ;-).

03 March 2008

Starting an external program in the same directory

Especially in development/demo scenario's you sometimes need to start an external program. In my case, it was a simple batch file that more or less terminated and restarted a Map Server service in a rather ungraceful way. But sometimes you want to go for simple. First, you have to find out in which directory your external program is. This is the same directory as where your program runs:
string assemblyBasePath =
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
then, you have to create the full path to your executable, for instance
string exec = Path.Combine(assemblyBasePath, "yourbatchfile.bat");
and finally, you have to launch the process:
ProcessStartInfo psi = new ProcessStartInfo(exec);
psi.WindowStyle = ProcessWindowStyle.Hidden;
Process proc = Process.Start(psi);
proc.WaitForExit();
and that's all there is to it. The call to proc.WaitForExit() makes sure that your own program waits for the batch file "yourbatchfile.bat" to complete, while ProcessWindowStyle.Hidden prevents a console window popping up. If you do want to see the console window, for debugging purposes for example, use ProcessWindowStyle.Normal instead

28 February 2008

Forcing a web service proxy to use a specific http version

A short one this time, and a rare one too, but taken from real life. Sometimes a web service is implemented in such a way that it only understands http 1.1 or 1.0 but the proxy class that Visual Studio.NET generated does not know that (because the service is badly implemented, or for some other reason). If you cannot change the service implementation, you will have to change your client implementation. Say, you added a web reference to a web service and called the generated proxy class "MyService". The only thing you need to do is:
using System;
using System.Net;

namespace MyApplication
{
  public class MyFixedHTTPService : MyService
  {
    protected override WebRequest GetWebRequest(Uri uri)
    {
      HttpWebRequest w = base.GetWebRequest(uri) as HttpWebRequest;
      w.ProtocolVersion = HttpVersion.Version10;
      return w;
    }
  }
}
and then use this class to call your service. This forces the proxy to use HTTP 1.0. The best thing about the subclassing approach is that you can simply regenerate the proxy class if you need to, while still retaining your modifications

23 February 2008

Calling a WCF service from Javascript

Note - I wrote this a long time ago. While the information in this article is still valid, nowadays I would use ASP.NET MVC 4 WebAPI on the server, and jQuery on the client to do something like this. I will blog about this soon.

In a previous post I pointed out how to call an ASP.NET ASMX web service from javascript in the browser. Although this still works fine, the world has moved on to .NET 3.5 and WCF services have now replaced ASMX services. Luckily, these are also callable from javascript although the procedure is now a little bit different. In this sample I presume you can use Visual Studio 2008 and know a little about WCF.

1. Create an empty solution, and add a WCF service library to it

We'll call the solution JSONWCFTest, and the library JSONServices.

2. Add a data contract

using System.Collections.Generic;
using System.Runtime.Serialization;

namespace JSONServices
{
 [DataContract]
 public class SampleDataObject
 {
   public SampleDataObject(int NewId, string NewName)
   {
     Id = NewId;
     Name = NewName;
   }
   [DataMember]
   public int Id { get; set; }

   [DataMember]
   public string Name { get; set; }
 }
}

3. Add service contract

Add an interface IJSONService with the following methods using System.Collections.Generic; using System.ServiceModel;
namespace JSONServices
{
 [ServiceContract(Namespace="http://DotNetByExample/JSONDemoService")]
 public interface IJSONService
 {
   [OperationContract]
   SampleDataObject GetSingleObject(int id, string name);

   [OperationContract]
   ICollection GetMultipleObjects(int number);
 }
}

4. Add an implementing class

Implement the service contract like this
System.Collections.Generic;

namespace JSONServices
{
 public class JSONService : IJSONService
 {
   public SampleDataObject GetSingleObject(int id, string name)
   {
     return new SampleDataObject(id, name);
   }

   public ICollection<SampleDataObject> GetMultipleObjects(int number)
   {
     List<SampleDataObject> list = new List<SampleDataObject>();
     for (int i = 0; i < number; i++)
     {
       list.Add(new SampleDataObject(i, "Name" + i));
     }
     return list;
   }
 }
}
So far, this is very basic WCF stuff. Nothing special here.

5. Add new web application

Add a new project of type "ASP.NET Web Application" to the solution. Call it JSONTestApp. Add a reference to the JSONWCFTest project.

6. Add a SVC file to the web application

This part is a bit awkward. Choose "Text File", and name it "AjaxService.svc". Then open the file, and enter the following code
<%@ServiceHost language="C#" debug="true"
Service="JSONServices.JSONService"
Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"%>
It may be tempting to add an "Ajax-enabled WCF service" to the project but this creates its own operation contract, and in this example I want to simulate the situation in which I re-use an already existing operation contract implemented in a separate service library.

7. Check the javascript interface

Basically, you are done now. Your service is hosted callable from javascript. You can check right-clicking on AjaxService.svc, and you will now see a web page that will say something like "This is a Windows© Communication Foundation service. Metadata publishing for this service is currently disabled." and a lot things more. You can check the javascript interface by adding "/jsdebug" to the url displayed in your browser, in my case this is "http://localhost:1781/AjaxService.svc/jsdebug". This shows the dynamically generated javascript proxy that you can call in your client code:
Type.registerNamespace('dotnetbyexample.JSONDemoService');
dotnetbyexample.JSONDemoService.IJSONService=function() {
dotnetbyexample.JSONDemoService.IJSONService.initializeBase(this);
this._timeout = 0;
this._userContext = null;
this._succeeded = null;
this._failed = null;
}
dotnetbyexample.JSONDemoService.IJSONService.prototype={
_get_path:function() {
var p = this.get_path();
if (p) return p;
else return dotnetbyexample.JSONDemoService.IJSONService._staticInstance.get_path();},
GetSingleObject:function(id,name,succeededCallback, failedCallback, userContext) {
/// <param name="id" type="Number">System.Int32</param>
/// <param name="name" type="String">System.String</param>
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="userContext" optional="true" mayBeNull="true"></param>
return this._invoke(this._get_path(), 'GetSingleObject',false,{id:id,name:name},succeededCallback,failedCallback,userContext); },
GetMultipleObjects:function(number,succeededCallback, failedCallback, userContext) {
/// <param name="number" type="Number">System.Int32</param>
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="failedCallback" type="Function" optional="true" TomayBeNull="true"></param>
/// <param name="userContext" optional="true" mayBeNull="true"></param>
Note: FireFox displays the javascript directly in the browser; for security reasons, Internet Explorer wants to download it to a file rather than display it, but after saving it and opening it in a text editor you will see the text above. As you can see this contains a lot of plumbing - and this is only the top part - but I emphasized the parts that are interesting right now: the name of the object that you need to call from javascript (dotnetbyexample.JSONDemoService.IJSONService) and the methods, which have - surprise, suprise - exactly the same name as their C# server-side counterparts. From here on, the procedure is pretty much the same as we were used to when calling asmx webservices from javascript:

8. Add an Web Form to the Web Application

Call it TestForm1.aspx

9. Add a script manager and a reference

Add a script manager to the form, right below the form tag, and make a reference to the AjaxService.svc file:

<form id="form1" runat="server">
<asp:scriptmanager runat="server">
<services>
<asp:ServiceReference Path="AjaxService.svc" />
</services>
</asp:scriptmanager>

10. Add some user interface elements to call the service

Right below the script reference, add the following code:
<div>
ID<asp:TextBox ID="tbId" runat="server">21</asp:TextBox>
Name<asp:TextBox ID="tbName" runat="server">John Doe</asp:TextBox><br />
<asp:Button ID="btnSelect" runat="server" Text="SingleSelect"
   UseSubmitBehavior="False"  OnClientClick="CallSingle(); return false;"/>
</div>
<div id="result1"></div>

11. Add Javascript code

Add some javascript code to call the WCF service and process the results. Place this inside the head-tag, below the title tag:
<script type ="text/javascript">
function CallSingle()
{
dotnetbyexample.JSONDemoService.IJSONService.GetSingleObject(
    document.getElementById("tbId").value,
    document.getElementById("tbName").value,
    CallBackSingle );
}
function CallBackSingle( WebServiceResult )
{
resultDiv = document.getElementById("result1");
resultDiv.innerHTML = "You entered: id = " +
 WebServiceResult.Id + " name = " +
 WebServiceResult.Name;
}
</script>
Notice again that calling a WCF method from javascript works the same as when using asmx services: one extra parameter at the end of the list is required, which is the callback. This is a function that is called upon receiving the result from the server - the server method result is put into the single parameter of the callback.

12. Run the test page

Run Test1Form.aspx. You should be able to input and numerical id and a alphanumeric name, which are sent to the server, and returned back to you as and SampleObject.

13. Deploying WCF services in IIS

This all works fine when running it in Cassini, but when you want to host it in IIS, you will need to take care two things. First, you will need to ensure that IIS and WCF are correctly installed and registered. If IIS does not seem to want to cough up your SVC files (you can check that by trying http://<your host here>/<your sitename here>/AjaxService.svc), try running the command ServiceModelReg.exe /i /x from %WINDIR%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation. Restart IIS after running this command. Second, if you created a default ASP.NET 2.0 website, you may run into this error message:
IIS specified authentication schemes 'IntegratedWindowsAuthentication, Anonymous', but the binding only supports specification of exactly one authentication scheme. Valid authentication schemes are Digest, Negotiate, NTLM, Basic, or Anonymous. Change the IIS settings so that only a single authentication scheme is used.
To fix this, right-click the website in your IIS manager and choose "properties". Then click the "Directory" tab, click the "Edit" button in the "Anonymous access and authentication control" area. You will see that both Anonymous access and Integrated Windows Authentication are selected. Unselect one of them, then restart IIS. After that, the application should work smoothly.

Concluding remarks

Calling WCF services from javascript is even simpler than calling asmx services - you don't even have to mark a service as [ScriptService] anymore, you just put an .svc file into your web site with four lines of code, make a reference to an existing service library and you're done. The sample described here does not use the IJSONService.GetMultipleObjects method, but you can download a the complete source code which includes a second test page that does. Notice that although GetMultipleObjects returns a ICollection, in javascript this is translated into a simple array. Thus, you can also use data and operation contract that use generic types, as long as the can simply be translated into an array. Oh - and don't forget to remove "debug=true" from "AjaxService.svc" before publishing it on production. Complete code downloadable here. Author's note: this article is my most viewed posting by far: 20% the traffic of my blog goes to this page. Apparently it meets a growing need in knowlegde. Please spread the word, (and the link) and if you find any errors of have any additions, let me know. Compliments are appreciated as well.

14 January 2008

Compacting C# code using implicit properties, object initialization and lambda expressions

Not exactly hot science anymore - most could be distilled from Scott Guthrie's blog and numerous others, but this shows how you can use new C# 3.0 features to compact your code and make it more readable at the same time Suppose you have a simple person class sporting a first name, a last name and a birthdate. In the old days you would make something like this:
public class Person
{
    string _firstName;
    string FirstName
    {
        get
        {
            return _firstName;
        }
        set
        {
            _firstName = value;
        }
    }

    string _lastName;
    string LastName
    {
        get
        {
            return _lastName;
        }
        set
        {
            _lastName = value;
        }
    }

    DateTime _birthDate;
    DateTime BirthDate
    {
        get
        {
            return _birthDate;
        }
        set
        {
            _birthDate = value;
        }
    }
}
To create a list of these objects would be something like
List<Person> opList = new List<Person>
Person p1 = new Person();
p1.FirstName = "Joost";
p1.LastName = "van Schaik"
p1.BirthDate = new DateTime( 1969,06,03);
opList.Add( p1);
// etc.
To make things easier for you class user you could provide it with constructors, but as the numbers of properties grow, so does the number of (potential) constructors. To actually do something with the resulting list, you could do a foreach( OPerson p in opList) etc, or write something like this:
l.ForEach(delegate(Person p)
{
  Console.WriteLine(p.FirstName);
});
It works but I always thought this to be a bit of an awkward way of making predicates Implicit properties For a class as simple as the Person, you don't need to define 'backing variables anymore. These are inferred from code. Therefore, we can refactor the person class like this:
public class Person
{
    public Person()
    {
    }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
}
That's rather compact, I'd say Object initalization The creation and initalization of a object can be written as follows:
Person p1 = new Person { FirstName = "Joost", LastName = "van Schaik", BirthDate=new DateTime( 1969, 06, 03)});
And while we are at it, the creation of a list of persons could be even simpler:
List<Person> l= new List<Person>
{
    new Person { FirstName = "Joost", LastName = "van Schaik", BirthDate=new DateTime( 1969, 06, 03)},
    new Person { FirstName = "John", LastName = "Doe", BirthDate = new DateTime(1970, 01, 01) },
    new Person { FirstName = "Michel", LastName = "van Schaik", BirthDate = new DateTime(1970, 12, 25) }
};
Lambda expressions And finally, picking out the first name myself and my family members would require only one line:
List<Person> vanSchaik = l.FindAll(p => p.LastName == "van Schaik");
And writing them out, too
vanSchaik.ForEach(p => Console.WriteLine(p.FirstName));
Conclusion The new features of C# can be used to make code more compact and better readable at the same time. Lambda expressions is certainly something you need to get used to reading, but for simple expressions they make life a heck of a lot easier. Complex expressions are hard to understand and read, though. Keep in mind that the next programmer may have a hard time reading your code, so don't use it just for the sake of it.