Welcome to MSDN Blogs Sign in | Join | Help

Windows Vista Ultimate Update (Tinker)

There is a new game included in one of the latest Vista Ultimate Update. It is a puzzle game that is really addictive.

You can also record a video, within the game...

Posted by davidhernandez | 0 Comments
Filed under: ,

4 hours with Silverlight (and Hosting)

After watching some of the great tutorial videos in Silverlight.net I decided to play a little bit with Silverlight 2 and VS2008.

It is incredible all the funcionality that offers Silverlight with a plugin of 4.5 MB (WCF, Drawing, DataBinding, Linq ....) But what is even more incredible is the productivity you get right from the beggining. A .Net programmer doesn't have a deep learning curve and can accomplish many tasks within minutes.

The first Silverlight component I decided to do was a simple rotator (I know there are tons of them and very good ones) but I wanted to do my own and make it configurable so I could set the images by using the InitParameters. All of the things I needed to know where on the video tutorials.

The only glitch was finding a free hosting site to make my silverlight component public. Some hosting sites are not prepared to host Silverlight, why? Since Silverlight is just a .xap file that gets downloaded to the client and the plugins executes it. Theoretically you only need a web server to host a file and an html/php/asp.net (you name it) file to embed the SL control. Well, the problem is the xap extension, some hosting sites ban any "unkown" extension, and some doesn't have configured the MIME type for it. Therefore you end up thinking that the hosting site cannot host SL2 or that SL2 sucks. Read on ...

There is a codeplex article about writing an httphandler to bypass the hosting "type check" http://www.codeproject.com/KB/silverlight/XamlWithoutMime.aspx but of course this will only work in asp.net enabled sites.Read on ...

Well some people think a .xap file is some obscure binary file that only MS can understand, but in many places it is said that a .xap file is just a zip file that contains two files (a xaml manifest and a dll assembly) zip file??? What if I rename the xap file into zip, change the html code to tell that my SL2 control is in a zip file and then I upload it to a "Silverlight not prepared" hosting site. IT WORKS. Here is the proof!

http://aspspider.net/dhdiez/PhotoRotatorTestPage5.html

 

The html code to host the app is here:

<body>

<!-- Runtime errors from Silverlight will be displayed here.

This will contain debugging information and should be removed or hidden when debugging is completed -->

<div id='errorLocation' style="font-size: small;color: Gray;"></div>

<div id="silverlightControlHost">

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">

<param name="initparams" value="imagen1=http://aspspider.net/dhdiez/images/rw1.jpg,

imagen2=http://aspspider.net/dhdiez/images/rw2.jpg,

imagen3=http://aspspider.net/dhdiez/images/rw3.jpg,

imagen4=http://aspspider.net/dhdiez/images/rw4.jpg,

imagen5=http://aspspider.net/dhdiez/images/rw5.jpg,

imagen6=http://aspspider.net/dhdiez/images/rw6.jpg,

imagen7=http://aspspider.net/dhdiez/images/rw7.jpg,

imagen8=http://aspspider.net/dhdiez/images/rw8.jpg,

imagen9=http://aspspider.net/dhdiez/images/rw9.jpg,

imagen10=http://aspspider.net/dhdiez/images/rw10.jpg,

imagen11=http://aspspider.net/dhdiez/images/rw11.jpg,

imagen12=http://aspspider.net/dhdiez/images/rw12.jpg,

imagen13=http://aspspider.net/dhdiez/images/rw13.jpg,

imagen14=http://aspspider.net/dhdiez/images/rw14.jpg,

imagen15=http://aspspider.net/dhdiez/images/rw15.jpg,

imagen16=http://aspspider.net/dhdiez/images/rw16.jpg" />

<param name="source" value="ClientBin/PhotoRotator.zip"/>

<param name="onerror" value="onSilverlightError" />

<param name="background" value="white" />

<param name="minRuntimeVersion" value="2.0.31005.0" />

<param name="autoUpgrade" value="true" />

<a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">

<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>

</a>

</object>

<iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>

</div>

</body>

Posted by davidhernandez | 0 Comments
Filed under: ,

PDC videos

Here are the videos of the PDC. Just the week after the end of the PDC we can see all the presentations of the PDC that shows us present and future of Microsoft Development.

http://channel9.msdn.com/pdc2008/

Here we can see the presentation of Windows Azure, Windows 7, Visual Studio 10, Team Foundation, Silverlight, C# 4.0, Office 14, Live services, Paralell Computing Platform ...

It's the End for Windows 3.11!!

Many people has echoed the news about extending the life of OEM Windows XP.

But there is not much fuss about that Windows 3.11 is going to be discontinued in embedded in 3 months (November 1st 2008) ... 16 years after its release!

 

win311logo 

John Coyne's Embedded Blog : It's the End for 3.11!!

Web References in Visual Studio 2008

Some guys has asked about what happened to the Web References in Visual Studio 2008.

Well if we pay a little bit of attention, by default in VS2008 there is no right button over the project -> "Add Web Reference". There is a "Add Service Reference" (without Web) that means it is using a Reference to a service no matter which protocol is using (This is something not enough stressed a Service doesn't imply to be a web service).

This Service Reference is in fact a WCF proxy (if we look to the .config file we can see that after adding a Service Reference  can see a section called system.serviceModel, bindings and so on.

If we need to create a classic "old style" web reference we still have the option to do so ... just look at this 50" video....

 

(In order to see a high-res video check SkyDrive: http://cid-ae1cb866e9c0b985.skydrive.live.com/self.aspx/Public/Classic-Web-Services-In-Visual-Studio-2008.wmv)


Video: Classic Web Services Reference in Visual Studio 2008

Strong Naming Guidance Application Block for Visual Studio 2008

Enterprise Library 4.0 has been released and the Strong Naming Guidance Application Block has been removed from the EntLib, but it is available as a separate download in entlibcontrib:

The direct link is here:

http://www.codeplex.com/entlibcontrib/SourceControl/DownloadSourceCode.aspx?changeSetId=18160 (Note that this is not a stable release)

If you are too lazy busy to download, open VS and compile you can download here the msi.

First impressions of Visual Studio 2008

Now that there is a new release of Visual Studio I wanted to take a closer look at it to see which are the improvements and new features.

I really wanted to get to the new stuff about Linq and the .Net framework 3.5. But I got lost fiddling with the new UI, specially the new refactor functionality.

I really liked the "Organize Usings", which takes a file and removes all the unnecessary using clauses and order the rest of them. That is prety useful since some times you can see files that their using region is larger than the code inside, and most of them are just left overs of old code or some temporary test. It is really annoying to see so many usings since many times you end up analyzing the code or removing the using and compiling the project to check if it really being used. So, the fact is that you get distracted.

The only "but" to this utility is that it only does the job on a single file, instead of all the project or solution. So I decided to create an Ad-in so I could also test the extensibility of Visual Studio. I was really impressed that in less than two hours I had a working Add-in that removed and sorted all the using of the .cs files. You can find an attached RemoveAndSortAllusings.zip file with the code. Of course it is a really rough add-in and lots of things are missing, like using a custom Icon, or dealing with files in source control, but at least is a start.

using System;
using Extensibility;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.CommandBars;
using System.Resources;
using System.Reflection;
using System.Globalization;
using System.Windows.Forms;

namespace RemoveAndSortAllusings
{
    /// <summary>The object for implementing an Add-in.</summary>
    /// <seealso class='IDTExtensibility2' />
    public class Connect : IDTExtensibility2, IDTCommandTarget
    {
        /// <summary>Implements the constructor for the Add-in object. Place your initialization code within this method.</summary>
        public Connect()
        {
        }

        /// <summary>Implements the OnConnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being loaded.</summary>
        /// <param term='application'>Root object of the host application.</param>
        /// <param term='connectMode'>Describes how the Add-in is being loaded.</param>
        /// <param term='addInInst'>Object representing this Add-in.</param>
        /// <seealso class='IDTExtensibility2' />
        public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
        {
            _applicationObject = (DTE2)application;
            _addInInstance = (AddIn)addInInst;
            if(connectMode == ext_ConnectMode.ext_cm_UISetup)
            {
                object []contextGUIDS = new object[] { };
                Commands2 commands = (Commands2)_applicationObject.Commands;
                string toolsMenuName;

                try
                {
                    //If you would like to move the command to a different menu, change the word "Tools" to the 
                    //  English version of the menu. This code will take the culture, append on the name of the menu
                    //  then add the command to that menu. You can find a list of all the top-level menus in the file
                    //  CommandBar.resx.
                    string resourceName;
                    ResourceManager resourceManager = new ResourceManager("MyAddin2.CommandBar", Assembly.GetExecutingAssembly());
                    CultureInfo cultureInfo = new CultureInfo(_applicationObject.LocaleID);
                    
                    if(cultureInfo.TwoLetterISOLanguageName == "zh")
                    {
                        System.Globalization.CultureInfo parentCultureInfo = cultureInfo.Parent;
                        resourceName = String.Concat(parentCultureInfo.Name, "Tools");
                    }
                    else
                    {
                        resourceName = String.Concat(cultureInfo.TwoLetterISOLanguageName, "Tools");
                    }
                    toolsMenuName = resourceManager.GetString(resourceName);
                }
                catch
                {
                    //We tried to find a localized version of the word Tools, but one was not found.
                    //  Default to the en-US word, which may work for the current culture.
                    toolsMenuName = "Tools";
                }

                //Place the command on the tools menu.
                //Find the MenuBar command bar, which is the top-level command bar holding all the main menu items:
                Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["MenuBar"];

                //Find the Tools command bar on the MenuBar command bar:
                CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName];
                CommandBarPopup toolsPopup = (CommandBarPopup)toolsControl;

                //This try/catch block can be duplicated if you wish to add multiple commands to be handled by your Add-in,
                //  just make sure you also update the QueryStatus/Exec method to include the new command names.
                try
                {
                    //Add a command to the Commands collection:
                    Command command = commands.AddNamedCommand2(_addInInstance, "RemoveAndSortAllUsings", "Remove and Sort ALL usings", "Executes the command to remove and sort all usings in cs files.", true, 213, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);

                    //Add a control for the command to the tools menu:
                    if((command != null) && (toolsPopup != null))
                    {
                        command.AddControl(toolsPopup.CommandBar, 1);
                    }
                }
                catch(System.ArgumentException)
                {
                    //If we are here, then the exception is probably because a command with that name
                    //  already exists. If so there is no need to recreate the command and we can 
                    //  safely ignore the exception.
                }
            }
        }

        /// <summary>Implements the OnDisconnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being unloaded.</summary>
        /// <param term='disconnectMode'>Describes how the Add-in is being unloaded.</param>
        /// <param term='custom'>Array of parameters that are host application specific.</param>
        /// <seealso class='IDTExtensibility2' />
        public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
        {
        }

        /// <summary>Implements the OnAddInsUpdate method of the IDTExtensibility2 interface. Receives notification when the collection of Add-ins has changed.</summary>
        /// <param term='custom'>Array of parameters that are host application specific.</param>
        /// <seealso class='IDTExtensibility2' />        
        public void OnAddInsUpdate(ref Array custom)
        {
        }

        /// <summary>Implements the OnStartupComplete method of the IDTExtensibility2 interface. Receives notification that the host application has completed loading.</summary>
        /// <param term='custom'>Array of parameters that are host application specific.</param>
        /// <seealso class='IDTExtensibility2' />
        public void OnStartupComplete(ref Array custom)
        {
        }

        /// <summary>Implements the OnBeginShutdown method of the IDTExtensibility2 interface. Receives notification that the host application is being unloaded.</summary>
        /// <param term='custom'>Array of parameters that are host application specific.</param>
        /// <seealso class='IDTExtensibility2' />
        public void OnBeginShutdown(ref Array custom)
        {
        }
        
        /// <summary>Implements the QueryStatus method of the IDTCommandTarget interface. This is called when the command's availability is updated</summary>
        /// <param term='commandName'>The name of the command to determine state for.</param>
        /// <param term='neededText'>Text that is needed for the command.</param>
        /// <param term='status'>The state of the command in the user interface.</param>
        /// <param term='commandText'>Text requested by the neededText parameter.</param>
        /// <seealso class='Exec' />
        public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText)
        {
            if(neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
            {
                if (commandName == "RemoveAndSortAllusings.Connect.RemoveAndSortAllUsings")
                {
                    status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;
                    return;
                }
            }
        }

        /// <summary>Implements the Exec method of the IDTCommandTarget interface. This is called when the command is invoked.</summary>
        /// <param term='commandName'>The name of the command to execute.</param>
        /// <param term='executeOption'>Describes how the command should be run.</param>
        /// <param term='varIn'>Parameters passed from the caller to the command handler.</param>
        /// <param term='varOut'>Parameters passed from the command handler to the caller.</param>
        /// <param term='handled'>Informs the caller if the command was handled or not.</param>
        /// <seealso class='Exec' />
        public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
        {
            handled = false;
            if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
            {
                if (commandName == "RemoveAndSortAllusings.Connect.RemoveAndSortAllUsings")
                {
                    handled = true;

                    if (!_applicationObject.Solution.IsOpen)
                    {
                        MessageBox.Show("There is no solution to eliminate usings.");
                    }
                    else 
                    {
                        foreach (Project p in _applicationObject.Solution.Projects)
                        {
                            SearchInProject(p);
                        }
                    }

                    return;
                }
            }
        }

        private void SearchInProject(Project project)
        {
            SearchInProjectItem(project.ProjectItems);
        }

        private void SearchInProjectItem(ProjectItems projectItems)
        {
            if (projectItems == null)
            {
                return;
            }


            foreach (ProjectItem projectItem in projectItems)
            {
                //Eliminate the unnecessary using in cs files.
                if(projectItem.Name.EndsWith(".cs"))
                {
                    bool wasOpened = false;
                    if (projectItem.get_IsOpen(Constants.vsViewKindCode))
                    {
                        wasOpened = true;
                    }

                    Window w = projectItem.Open(Constants.vsViewKindCode);
                    w.Activate();
                    _applicationObject.ExecuteCommand("Edit.RemoveAndSort", "");

                    if (!wasOpened)
                    {
                        w.Close(vsSaveChanges.vsSaveChangesYes);
                    }
                    
                }
                
                
                if (projectItem.SubProject != null)
                {
                    SearchInProject(projectItem.SubProject);
                }
                else
                {
                    SearchInProjectItem(projectItem.ProjectItems);
                }
            }
        }


        private DTE2 _applicationObject;
        private AddIn _addInInstance;
    }
}
Posted by davidhernandez | 1 Comments
Filed under:

Attachment(s): RemoveAndSortAllusings.zip

.Net Framework Source Code released

The .Net Framework 3.5 Source Code will be released later this year.
(announced in http://weblogs.asp.net/scottgu/archive/2007/10/03/releasing-the-source-code-for-the-net-framework-libraries.aspx)

This isn't going to be a major revolution since the code was already "visible" using tools like Reflector.
But now we will have the complete detail of the source code (private variables names, comments ...) and we will also have the possibility to debug it with Visual Studio 2008. So we can understand better what's "under the hood" and in a much easier way.

Posted by davidhernandez | 1 Comments
Filed under:

Mad.Nug Event Enterprise Library 3.1

I will be speaking about the new version of Enterprise Library 3.1 at the madrid .Net User group event in July 19.
It is a two hour dynamic presentation with demos where people can participate, ask questions or share their oppinions/experiences.

The madNug events are held at Microsoft's Madrid office

Paseo del Club Deportivo, 1
Centro Empresarial La Finca - Edificio 1
28223 Pozuelo de Alarcón (Madrid)
Tel: 91 391 99 99

The event will be held in spanish so here is the agenda:

  • Breve Introducción a la Enterprise Library
  • Que ha cambiado de la Entlib 2.x a 3.x
  • Introducción a Aspect Oriented Programming (AOP)
  • Policy Injection Application Block
    • Demo
  • Validation Application Block
    • Demo
  • WCF & Enterprise Library
    • Demo
  • Automation
    • Demo 

 

      Attendance is free but registration is required. The invitation will be send by MSDN Flash and published in http://www.microsoft.com/spanish/msdn/spain/eventos/comunidad.mspx

 

      Register:

      http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032345749&Culture=es-ES

 

Posted by davidhernandez | 0 Comments
Filed under: ,

Encrypting long text asymmetrically

One of the recurring tasks that everybody has made in every programming language has been asymmetric encryption.

With .Net it is very simple to encrypt data, it is well documented and there are lots of blogs and articles, but people still run into two common issues.

The first one is what most people want to do is encrypt a text, not a number or a sequence of bytes. The .Net framework has implemented the most popular algorithms, and they are all based on byte arrays. There are many blogs and articles that talk about how to convert strings to byte arrays and vice versa. The most common solution is to use Encoding.Convert.

The second most typical issue (and I think less talked/blogged about) is the length limitation of the asymmetric encryption. This limitation comes from the mathematical algorithm they are based. The length varies depending on the key size used. When trying to encrypt a long string a System.Security.Cryptography.CryptographicException exception is raised stating a "Bad length" or "Key not valid for use in specified state" message.

In order to overcome this limitation there are two widely implemented (but not standardized) solutions.

The first one is to divide the text to be encrypted into chunks, encrypt the chunks and concatenate the result. When decrypting we need to divide the encrypted message in chunks, decrypt the chunks and concatenate the result.

The attached code has a EncryptByChunks/DecryptByChunks that shows a sample of this implementation using an RSACryptoServiceProvider. This sample could be improved by calculating the size of the chunks based on the Key size.

 

 

The second solution consist on using a symmetric algorithm. The idea is to generate a random symmetric key, encrypt the message with that key, encrypt the symmetric key with the asymmetric public key. When decrypting the message, first we decrypt the symmetric key with the asymmetric private key, then decrypt the message using the decrypted symmetric key. This is (what more or less) SSL does.

The attached code has a EncryptWithSymmetricAid/DecryptWithSymmetricAid that shows a sample of this implementation. It uses RSACryptoServiceProvider for the asymmetric algorithm and TripleDESCryptoServiceProvider for the symmetric.

 

 

Running a couple of rudimentary "stress" testing with a loop of 1000 iterations and a message of 1 MByte we can see that the symmetric-aided approach takes approximately 10 times less to complete (4 seconds versus 39 seconds) than the "chunk" solution.

 

Note: Never try to implement a custom encryption algorithm by yourself, always use a known encryption algorithm. (That of course may not apply to renowned mathematicians that like programming)

This has been said many times but people keep falling into the error of ignoring the suggestion, therefore keeping a false feeling of safety.

Posted by davidhernandez | 2 Comments
Filed under:

Attachment(s): DHDRSAEncription.zip

Policy Injection App. Block simple sample

Now with the new version of Enterprise Library 3.0 we can play with Aspect Oriented Programming.

The goal of AOP is to insert some functionality that is not "business related" without altering the existing code or to make it flexible enough so changes are smooth or even better, transparent. The idea is to intercept calls before and after a method is called.

Some of this functionality could be tracing, transactions, performance counters, exception handling, security etc ...

In web scenarios some of this behaviors could be accomplished through httpmodules or http handlers, or SOAP filters. But only, of course, in the entry points of the pages or web services facades. Now it can be implemented in all kind of classes.

The Policy Injection Application Block (PIAB) is great mainly because of its simplicity of use.

There are lots of already built matching rules so we can filter which code we want to intercept to make our "extra functionality" (of course we would seldom want to intercept all calls we want to limit it to an assembly or a namespace) If by some chance this set of rules fall short we could implement a custom one.

Also there are ready build handlers (interceptors), which are great examples and covers the most wanted extra functionality. And of course we can build our own handlers.

 

Here are a couple of samples on how to use it.

The first sample shows how to use the  performance counter. We can achieve it with three steps:

  • Register the performance counter

Just run installutil /category=MyClassCategory Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.dll (from the bin folder of the Enterprise Library )

  • Decorate the method

Set the "PerformanceCounterCallHandler" attribute in the method we want to create the performance counter.

 

[PerformanceCounterCallHandler("MyClassCategory","MyInstanceName2")]

public string MyMethod(string param1)

 

  • Create the wrapped object

IMyClass myClassInstance = (IMyClass)PolicyInjection.Create<MyClass, IMyClass>();

 

Once done that we can call the method and the performance counter will be created and managed automatically.

 

Using perfmon we can see how the performance counter is incremented every time the method is called.

 

 

 The second sample shows how to intercept the exceptions from a method and modify the return value in order to modify the return value of the original method.

We needed to create a handler to manage the exceptions, to make a handler we need to create a class that inherits ICallHandler and decorate it with the ConfigurationElementType attribute.

In the Invoke method we implement the exception handling. If there is some exception in the message we disable it by setting it to null and then we change the return value.

 

public IMethodReturn Invoke(IMethodInvocation input,
GetNextHandlerDelegate getNext)
{

IMethodReturn msg = getNext()(input, getNext);

if (msg.Exception != null)
{
     msg.Exception = null;
     msg.ReturnValue = "Message Exception caught by MyMessageHandler."
}

return msg;

}

 

Then we need to create a policy in the config file of the application to set which code should be intercepted.

With this version of EntLib you can right click the .config file inside Visual Studio 2005 and and select "Edit Enterprise Library Configuration".

Add the Policy Injection Application Block

Add a new policy

if In this sample we created a namespace matching rule and added one namespace name to the collection.

The we added our handler and we are ready to go!

 

 

Don't forget that we still need to wrap the objects being intercepted. We have two options we can create a new object that will be wrapped:

IMyClass myClassInstance = (IMyClass)PolicyInjection.Create<MyClass, IMyClass>();

or wrap an existing object:

MyClass myClassInstance = new MyClass();

IMyClass proxy = PolicyInjection.Wrap<IMyClass>(myClassInstance);

 

The last sample is a tracing handler which the interception works as the previous sample and what changes is the implemented handler. We wanted to create a file that contains the traces with the incoming parameters and its values and the return values. Here's the entire code of the handler:

 

[ConfigurationElementType(typeof(CustomCallHandlerData))]
public class MyTraceHandler : ICallHandler
{

public MyTraceHandler(object o)
{

}

public IMethodReturn Invoke(IMethodInvocation input,
GetNextHandlerDelegate getNext)
{


buildInput(input);

IMethodReturn msg = getNext()(input, getNext);

buildOutput(msg.ReturnValue);

return msg;
}

private void buildOutput(object p)
{

System.IO.File.AppendAllText("C:\\PIABSimpleSampleTrace.txt", "OUTPUT: " + p.ToString() + "\r\n\r\n\r\n\r\n");

}

private void buildInput(IMethodInvocation input)
{


ParameterInfo[] pis = input.MethodBase.GetParameters();

StringBuilder sb = new StringBuilder();
foreach (ParameterInfo pi in pis)
{
sb.Append(pi.Name + ":" + input.Arguments[pi.Name].ToString());
}

System.IO.File.AppendAllText("C:\\PIABSimpleSampleTrace.txt", "METHOD CALLED: " + input.MethodBase.Name + "\r\n");
System.IO.File.AppendAllText("C:\\PIABSimpleSampleTrace.txt", "INPUT: " + sb.ToString() + "\r\n");

}

}

 

 

Enjoy.
Posted by davidhernandez | 2 Comments
Filed under:

Attachment(s): PIABSimpleSample.zip

WSDL Merger

Working with Web Services is supposed to be interoperable, but that's not quite 100% true, there are always some glitches when working with other platforms.

Recently I faced one of those. With .Net I could easily create and consume web services by using WSDLs that had imports, but it seems that some tools don't support that keyword so I had to merge all the generated files (wsdl and xsds) into a single one.

Searching a little bit in live.com (http://search.live.com/results.aspx?q=%22wsdl+merger%22) I found a link to a post that had a really simple tool (and really helpful) to do the task.

Link to António Cruz : WSDL Merger

Carnival in Codeplex!

Ok, since I don't have time for nothing I started a new activity...

I have uploaded to the codeplex site the specifications of a new application called Carnival. This application is meant for masking data from a database.

The idea is quite simple. Take data from a database and obfuscate in some way to keep sensitive data (creditcards, telephones, addresses etc) safe from people that shouldn't view it. Those "undesirable" people could be QA and developers, which will need to use an application with realistic data (in volume and form) so they can test that the application will work as expected in production.

I have worked in many companies and I have always (very few exceptions) seen that many people across an enterprise had access to sensitive data. This data could be very valuable for competitors or other parties that could "persuade" some of those numerous guys to share it. In fact I am impressed that it happens so seldom (that I know of). Maybe we are only aware of these kind of transactions when they get published in the internet.

Probably everytime this data gets disclosed, some guy (CEO,CIO or project manager) gets fired. So I am impressed that very few enterprises use some kind of method to protect that data.

So here comes this application to the rescue.

 

Since I don't have time for nothing, and less to build this app. I will try to merge this activity with my training so this app will be built using the Enterprise Library 3.0, apply the best patterns and practices. It will have a GUI made with WPF which will transmit commands to the masking engine through WCF.

 

And last but not least (in fact the most important) Feedback! Now that I am in the planning phase I would love to hear some feedback before I start coding.

Generating documentation

 

I have seen many projects with a lot of documentation and also projects with almost no documentation and almost none that have the right amount of documentation.

Some methodologies require writing a lot of docs (planning, design etc ...) before starting to write some code, those docs became the pillars and the foundation of the projects, but in real life change happen. Therefore all the docs become outdated pretty fast so anyone looking for something useful in that documentation becomes impossible. People come to the project and they waste a lot of time reading documents that are inaccurate, they will have a wrong idea about something, will "break" it and then time will be spent to fix it, the person will be notified that he made something wrong, he will tell that he read it in some document, then it will be told that some documents are not updated so since discerning between what's right and what's wrong in the docs is so complicated they finally give up with the docs (after wasting lots of time).

 

Some other projects that are poorly documented, mostly because the managers have faced the "lots of docs" situation (or they lack any kind of methodology) and they say that documentation is not important and that anyways it becomes out dated. People come to the project and since there are no documents they will start working with no standards, making errors and making other people loose time fixing them and explaining them that even though there are no docs there are many unwritten laws that must be followed.

I am not a document lover, in fact, I hate documenting. But it is necessary, so, the question is: which is the correct approach? My personal view is a balanced course. Not too much and not few.

Write documentation when you plan any project, otherwise you won't be able to share ideas with the customer or to have any formal agreement about what is going to be built. Write documentation when designing, therefore you will have a plan how to build it. This manually generated documentation should be as brief as possible. I have seen documents of 200 pages that transmit an idea that could be communicated in 10 pages. (If you want to be the next Tolkien or Cervantes you are in the wrong profession, or at least do it in your spare time). I see this documentation as "historic" that means it shouldn't be updated, put a date on it and mark it as read-only.

Then think of what kind of documentation is going to be "alive" (that needs to be updated) that is going to be useful and that it will save more time than it will take updating the docs. This could be, for example, the API of the common components, user manuals and coding standards/best practices. Include in your estimations the task that it takes to update the documentation, otherwise this approach will fail since people will forget to do it or they won't have time to do it.

Some guy should have a role that will be the document manager (normally the guy in charge of standards and methodology)

Don't store that documentation in a "hidden" place. Make it visible. Centralize it; don't scatter the docs between many places, that way finding it will be hard enough for developers to forget updating the docs.  A good place to store it is SharePoint, it centralize the documentation, it can manage access rights so only the right people can modify it and the rest can view it, it notifies the team when a document has been updated, and it is easy to update and collaborate among team members. not all has to be in a word document, SharePoint can manage WIKIs (which can be a good tool to document the most common errors ) and forums (which may be a good tool to discuss how to solve a tricky problem, therefore leaving a written evidence on how a conclusion was  reached)

Once you have the documentation, don't stop at that point and try to automate as much as you can. If you have a standards documentation try using tools like FxCop to enforce it by writing your own rules (Visual Studio 2005 has that tool built in). Developers will read docs but they may forget it. FxCop will remind them.

For API documentation, use automatic document generation tools like SandCastle. The documentation will be comments in your source code and a chm help file will be automatically generated from the source code. 

I will expand more on these two useful tools in next posts.

More Posts Next page »
 
Page view tracker