SmartCodeGenerator with NAnt and Cassini – Please vote.

I have uploaded SmartCodeGenerator 2.7.0 today. This release ships with scg_console.exe which integrates NAnt and Cassini with SmartCodeGenerator development cycle.

I have also uploaded a new article at CodeProject demonstrating “How to use SCG along with NAnt and Cassini.”

Smart Code Generator: Code Generation experience with ASP.NET, NAnt and Cassini
This article describes how NAnt and Cassini can be integrated with the Smart Code Generator development cycle. This article can also used as a reference for ASP.NET developers who want to build, run and deploy ASP.NET projects seamlessly using NAnt and Cassini.
http://www.codeproject.com/useritems/smartcodegeneratorconsole.asp

Please vote the article.

WebMethod parameter as ref

I came across WebMethods where parameter is passed as ref. But is this a good practice?

//Option1 with ref
[WebMethod]
public void Transaction2(ref Test test )
{}

As opposed to writing

//Option2
[WebMethod]
public Test Transaction1(Test test )
{}

But we should be aware that when we do like this in WebMethod it does not work the same as normal programming concept where a ref points to the same storage location of the calling variable.

If we look carefully in the Proxy that .Net Generates we will find the followings:

//Option1 with ref
public void Transaction2(ref Test test) {
object[] results = this.Invoke(“Transaction2″, new object[] {
test});
test = ((Test)(results[0]));
}


as opposed to

//Option2
public Test Transaction1(Test test) {
object[] results = this.Invoke(“Transaction1″, new object[] {
test});
return ((Test)(results[0]));
}

here the result is casted back to (Test) and value is assigned to the ref variable.

If we look at the soap response of both Transaction1 and Transaction2 we find pretty much the same response, and Test object is created as part of the Response with its value.

//Option 1 with ref

<?xml version=”1.0″ encoding=”utf-8″?>
<soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/”>
  <soap:Body>
    <Transaction2Response xmlns=”http://tempuri.org/”>
      <test>
        <input>string</input>
        <output>string</output>
      </test>
    </Transaction2Response>
  </soap:Body>
</soap:Envelope>

as opposed to






//Option 2

<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <Transaction1Response xmlns="http://tempuri.org/"> <Transaction1Result> <input>string</input> <output>string</output> </Transaction1Result> </Transaction1Response> </soap:Body> </soap:Envelope>

Though both the options results in similiar result still its strongly recommeded is to use a single class to encapsulate all the output parameter (if possible also input parameters). The reason is mainly considered from webservice’s interoperability. Normally webservices are designed to be exposed to external systems and possibly it will be called from multiple heterogenous client platform. Also ref is not supported by many platforms. For example if I am not wrong even in the .Net world currently we cannot call a webmethod implemented with a ref parameter for the MS Ajax.Net implementations.

Running SmartCodeGenerator Projects with Cassini

 

With Cassini SCG Projects can be distributed very easily. Cassini is a mini web server written with 100% managed code C#, moreover Cassini is free. Cassini requires as an operating system either Windows 2000 or Windows XP; furthermore, the .NET Framework must also be installed. I am not going into further details of Cassini here, for more information please visit the Cassini Forum. All we need to know is Cassini is an independent web server and has the capability of running Asp.Net application locally; as SCG is pure ASP.NET application we can take full advantage of Cassini. With Cassini installed, the end user do not require installation of Internet Information Server (IIS) or Visual Studio to run SCG Projects.

To run SCG Projects with Cassini mini web server
1. Download the latest build of Cassini from Microsoft’s www.asp.net Web site.
2. Install Cassini using the instruction provided by the Cassini Team.

3. After Cassini is successfully installed point Cassini to your desired SCG Project Folder. To do this specify port, virtual and physical path for example
CassiniWebServer c:\temp\ExampleProject 1234

In this example the physical path of the SCG Project “c:\temp\ExampleProject” and port “1234” is specified.


If you have used the default Cassini installation path the CassiniWebServer.exe will be located in the “C:\Cassini” Folder.

Run Cassini pointing to the desired SCG Project folder.


c:\cassini\CassiniWebServer c:\temp\ExampleProject 1234
Here physical path c:\temp\ExampleProject and port 1234 has been specified.

This will bring the following screen showing Cassini Mini Web Server has successfully run with the desired SCG Project.

4. Browse the SCG Project using Internet Explorer. We loaded our SCG Project in port 1234 so we have to browse using http://localhost:1234/

Get X509Certificate2 from a LDAP Server or Remote Machine

In Scenario1 I blogged how to get Certificate using the X509Store Class. Where I used something like this.

X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);

But after spending a bit of time with the X509Store I realized it has limitations. The StoreLoacation enum has only 2 options:

  • CurrentUser: The X.509 certificate store used by the current user.
  • LocalMachine: The X.509 certificate store assigned to the local machine. 

But I wanted to Load Certificate from a Remote LDAP Server

I googled a bit but did not find any solutions to use the X509Store to Load Certificates from a remote machine. Then I used System.DirectoryServices namespace, SearchResult Class and DirectorySearcher Class to do the same. All I had to do is to use the DirectorySearcher and define SearchScope and create a Filter to find the desired Certificate from the remote machine. Then I imported the Certificate into X509Certificate2 using the handy Import Method. And the code looks like this.

[WebMethod]
public byte[] GetRecipientCertificateFromLDAPStore()
{
SearchResultCollection col;
DirectorySearcher searcher = new DirectorySearcher();
string[] resultsFields = new string[] { “cn”, “mail”, “usercertificate;binary” };
//Pass the IPAddress and the Port of the LDAP Server.
string[] textArray1 = new string[] { “LDAP://”, “103.20.218.16”, “:”, “180”, “/c=blabla” };
searcher.SearchRoot = new DirectoryEntry(string.Concat(textArray1), null, null, AuthenticationTypes.None);
searcher.SearchScope = SearchScope.Subtree;
searcher.PropertiesToLoad.AddRange(resultsFields);
searcher.Filter =string.Format(“(&(cn={0})(mail={1}))”, “* *”, emailAddress);
col = searcher2.FindAll();


X509Certificate2 certificate1 = new X509Certificate2();
foreach (SearchResult result1 in col)
{
  IEnumerator enumerator2;
  try
  {
    enumerator2 = result1.GetDirectoryEntry().Properties[“usercertificate;binary”].GetEnumerator();
    while (enumerator2.MoveNext())
    {
      object obj1 = RuntimeHelpers.GetObjectValue(enumerator2.Current);
      certificate1.Import((byte[])obj1);
      //Can access different Properties for example:
      //certificate1.Subject;
      //
certificate1.SerialNumber;
      //certificate1.Version;
      //certificate1.NotBefore;
      //certificate1.NotAfter;
      //certificate1.Issuer;
      
      return certificate1.Export(X509ContentType.Cert);

    }
  }
  catch{….}

}

return null;

}


I have seen approaches where CAPICOM has been used to import certificates from remote machine. But that creates dependency on COM. I wanted to stick to Managed code and to use the new X509Certificate2 that ships with .Net Framework 2.0.

(Please Note: If anyone know a different better approach please let me know.)