Thursday, November 6, 2008

VSCT Designer

Long time since my last entry, I have just moved and have been extremely busy / chaotic during the last weeks. Back online now.

I've found the following tool this seems very interesting for anybody working with DSL or VSX: 
http://www.codeplex.com/VSCTDesigner

I did have a little problem with adding bitmaps and therefore I've created the following post in the Codeplex website.

Wednesday, July 9, 2008

How to copy hibernate.config to the VSTS Output Folder?

VSTS is now included by default in the standard/professional version of vs.net 2008. Until now i was using NUnit + TestDriver.net, etc.

I've decided to test VSTS and found 1 big problem : my nhibernate.config file was not copied to the output directory of the test output folder. I was expecting this to be automatically since I've set the "Always Copy" in the build property for the file.

Doing some basic Google searches I've noticed I am not the only guy having this problem.

The solution is to open the "localtestrun.testrunconfig" file which is added automatically to the solution by VSTS, go to "Deployment" and then add the file you want to deploy/copy.










Once this is done, the hibernate.config file copied every time we run a test. This can be seen in the image below. VSTS creates 1 output folder for each test run.

Saturday, June 28, 2008

Code Generation 2008 : more than just content

The conference is now over.

Besides the fact of being a very good conference, one the most important things is that during the conference I've met wonderful people. Not only we had a lot of fun together but also we discussed some very interest topics.

Pedro Molina , me , Alejandro Silva and Gaston Milano

It's was amazing to see how much we had in common and how much effort we had wasted trying to solve all of us the same stuff. We are working in our little isolated island without having ways to correctly shared/reuse some of the common concepts in our tools/products.

Besides there deep technical knowledge and wonderful ideas, the most important thing was that we had a lot of fun together.

Another person which I was very pleased to met from Microsoft was Jean-Marc Prieur (picture, and yes, the guy in the background is Steve Cook).

He was "extremely" helpful, always open to new ideas , listened far beyond the extend of his responsibility, stayed "after" the conference to keep listening.
"Chapeau!!!".

Later during next week I will write down more stuff related to my point of view of some very specific stuff I've learn.

Monday, June 23, 2008

DSL : Model References (Backplane)

A couple of months ago I've wrote this MSDN Forum post where I was a little bit confused (and surprised) with the way of solving DSL Model References.

Edward Bakker finally found out that in Rosario the VSX team is actually giving a standard solution for this problem. Here is a detail BLOG entry about his findings, which I found very interesting.

What I wonder is when (and package into what product? I hope/think it should be the SDK), this improvement will be available.I've tried to google based on "Microsoft.VisualStudio.ToolIntegration.Backplane.dll" and Edward's blog was the only result.

I will try to find this information in Code Generation conference which I will be attending this week.

Tuesday, April 8, 2008

ObjectDataSource : Manually controlling the sorting expression.

By default the GenWise ASP.NET Templates uses the object datasource SortParamterName. When that property is used , the objectdatasource will manipulate internally the sort expression (change to asc , desc) .

  269     ObjectDataSource runat="server" ID="ObjectDataSource1" TypeName="BOLayer.CustomerFactory"
  270                 SelectCountMethod="Count" EnablePaging="True" UpdateMethod="Save" DeleteMethod="Delete"
  271                 SortParameterName="pSortExpression" MaximumRowsParameterName="pMaxResult" StartRowIndexParameterName="pFirstResult"
  272                 SelectMethod="GetAll">
  273                 
  274                     Parameter Name="pSortExpression">Parameter>
  275                     Parameter Name="pCriteria">Parameter>
  276                 
  277                 
  278                     Parameter Name="CustomerID">Parameter>
  279                 
  280             ObjectDataSource>


For more advanced sorting scenarios you might want to manually control what's passed to the pSortExpression method parameter. This can be done in the following way :

Subscribe to the ObjectDataSource Selecting method (genwise does that automatically)
   44 ObjectDataSource1.Selecting += new ObjectDataSourceSelectingEventHandler(ObjectDataSource1_Selecting);



  253    protected void ObjectDataSource1_Selecting(object pSender, ObjectDataSourceSelectingEventArgs pEventArgs)
  254         {
  255             if (pEventArgs.ExecutingSelectCount)
  256                 pEventArgs.InputParameters.Remove("pSortExpression");
  257             else
  258                 pEventArgs.InputParameters["pSortExpression"] = _newSortExpression;
  259 
  260             pEventArgs.InputParameters["pCriteria"] = Browse1_GetCriteria();
  261         }

Where does _newSortExpression come from ?


  198         string _newSortExpression = null;
  199         protected void Browse1_Sorting(object pSender, GridViewSortEventArgs pEventArgs)
  200         {
  201             // Calls this method to adapt the sort syntax (required for Composite sorting).
  202             _newSortExpression = WebUtils.SortExpressionTransformer(pEventArgs);
  203             pEventArgs.Cancel = true;
  204         }


SortExpression Tranformer takes the ObjectDataSource parameters and manipulates them to make them compatible with the GenWise Factories sorting syntax.

Below is the code of this method:

   63   public static string SortExpressionTransformer(GridViewSortEventArgs pEventArgs)
   64     {
   65         if (pEventArgs == null) throw new ArgumentNullException("pEventArgs");
   66 
   67         if (pEventArgs.SortDirection == SortDirection.Ascending)
   68         {
   69             return pEventArgs.SortExpression;
   70         }
   71 
   72         string newSortExpression = pEventArgs.SortExpression;
   73         string DESC = " DESC";
   74 
   75         if (pEventArgs.SortDirection == SortDirection.Descending)
   76         {
   77             if (pEventArgs.SortExpression.Contains(","))
   78             {
   79                 // Case : We have a composite sorting ( Field1,Field2) 
   80                 newSortExpression = string.Empty;
   81                 string[] sortParts = pEventArgs.SortExpression.Split(',');
   82                 for (int i = 0; i <> 
   83                 {
   84                     string sortPart = sortParts[i];
   85 
   86                     int sortDirectionIndex = sortPart.IndexOf(DESC);
   87                     bool isDescending = (sortDirectionIndex > -1);
   88 
   89                     string property = sortPart;
   90                     if (isDescending)
   91                     {
   92                         // sta : udpate templates.
   93                         //property = sortPart.Substring(0, (sortPart.Length - sortDirectionIndex + 1));
   94                         property = sortPart.Substring(0, (sortPart.Length - sortDirectionIndex + 1 + DESC.Length));
   95                     }
   96 
   97                     if (i > 0) newSortExpression += ",";
   98                     newSortExpression += property;
   99 
  100                     // Only add the DESC to all except the last (Last one will be controlled automatically by the object datasource.
  101                     if (!isDescending)
  102                     {
  103                         if (i < (sortParts.Length - 1))
  104                             newSortExpression +=  DESC ;
  105                     }
  106                 }
  107                 pEventArgs.SortExpression = newSortExpression;
  108             }
  109         }
  110         return newSortExpression;
  111     }

Monday, April 7, 2008

GenWise generated project added to vs.net solution using Source control.

Several customers have asked me how they can integrate an existing GenWise project into their vs.net solutions. To be more specific, GenWise already generates 100% compatible project files, so what's the problem?

Well, If you want to add the generated project into an existing solution and at the same time you can to keep that solution in source safe ( or in sourcegear vault which I use and recommend) then you might hit some little problems.

Problem #1 : Every time you regenerate the project is seen as a "new" project for the solution.
The reason behind this is that when you add the project to the solution the .proj file is modified with specific source control information + and ID (Guid) is given, etc.
To solve this problem you can "copy/paste" this information from the "modified" version of the project file INTO the GenWise project, so when you re-generate you don't loose this info .

Click on the image to enlarge an example for the solution to problem #1.




Problem #2 : After you have added the project to a source control provider ( vss or vault) all the files will be automatically read-only (by default) so you need to explicity do a complete project check out before you use the regenerate options from GenWise.

Thursday, February 7, 2008

Custom Security MembershipProvider & Login attempts (MaxInvalidPasswordAttempts)

The Problem : Have a limit on the amount of possible logins when using a Custom provider.

Let's say that you write your own MembershipProvider (quite common if you want to use your own object model ..)

   11   public class MyMemberShipProvider : System.Web.Security.MembershipProvider
   12     {

Like many other articles explain, the most important Method is ValidateUser.
What very people often "forget"to mention is that all other features are not present in your provider. For example, the MaxInvalidPasswordAttempts is a property that you can set it to any number but nothing is going to happen.

In a Nutshell : you need to implement it yourself.

What I am showning below is a quite simple version but it's proves the point.

  180     public override System.Boolean ValidateUser(System.String pUsername, System.String pPassword)
  181         {
  182             if (pUsername.Equals("demo") && pPassword.Equals("demo"))
  183             {
  184                 return LoginSuccess();
  185             }
  186             return LoginFailed();
  187 
  188         }

LoginFailed() will basically return false but also it would do the check if another attempt should be granted or not:

  211     private bool LoginFailed()
  212         {
  213             //WebFailureAuditEvent.Raise(WebEventCodes.AuditFormsAuthenticationFailure);
  214             LoginFailuresCount++;
  215             if (LoginFailuresCount >= this.MaxInvalidPasswordAttempts)
  216                 throw new Exception("OK, that's it. Bye Bye");
  217 
  218             return false;
  219 
  220         }



You need to keep track of how many login failures :

  197  protected int LoginFailuresCount
  198         {
  199             get
  200             {
  201                 if (HttpContext.Current.Session["Failures"] == null)
  202                     return 0;
  203                 return (int)HttpContext.Current.Session["Failures"];
  204             }
  205             set
  206             {
  207                 HttpContext.Current.Session["Failures"] = value;
  208             }
  209         }


In the commented line where I was trying to Raise the "WebFailureAuditEvent", I read somewhere that I was a good idea to raise it but could not find any reference or example. If anybody knows how to do it --> please let me know.

Note: An improvement to this model would be to support "PasswordAttemptWindow" which in this case I did not implement.

Note: New Browser == new Session so it's not really state-of-the-art security technique it's a basic

Thursday, January 17, 2008

DSL - How to use DesignVerbs with shapes?

Although I've previously wrote in this post about how you could add Menu Commands to shapes, I am still searching for alternative (maybe better?) approaches for exposing commands from my domain classes.

Why? Because the other way is too complex (too many steps) and I have many actions/commands.

Every time you click on a shape, a PropertyGrid is used to expose the ShapeProperties + DomainProperties (yes, they are merged in the PropertyGrid).

So, one natural approach would be to think "Why not add DesignVerbs as done for Custom Controls?". This question was asked in the msdn forum with null replied (until now ;) )

What I did was combined the idea from Geoff Appleby with a Custom partial class for each shape (off course only for the ones you need some special command/verb).

This is how the final solution looks like:

As you can see, "My Custom Action" and "Synchronize" are my exposed Actions/Commands. Here is the code that defines what to show:

public DesignerVerbCollection Verbs
{
get {
DesignerVerbCollection verbs = new DesignerVerbCollection();
verbs.Add( new DesignerVerb("My Custom Action", new EventHandler(ExecuteAction1) ));
verbs.Add(new DesignerVerb("Synchronize", new EventHandler(Synchronize)));
return verbs;
}
}

private void Synchronize(object sender, EventArgs e)
{
ExampleElement element = this.ModelElement as ExampleElement;
if ( element == null ) return;
MessageBox.Show("Action 1 was executed on model Element:" + element.Name);
}

Off course it's not only that since you need to also implement 2 interfaces:

public partial class ExampleShape : DslDiagrams::NodeShape, IComponent, IVerbsHost
{

private ISite _site;

public ISite Site
{
get
{
if (_site == null)
_site = new VerbSite(this, new VerbMenuCommandService(this));
return _site;
}
set { _site = value; }
}

public interface IVerbsHost { DesignerVerbCollection Verbs { get; }}

Drop me an e-mail if you are interested in the complete source code ( blogger does not have file upload i think.. need to check..)

TODO : Next I would like to combine both techniques be able to access this design verbs not only from the PropertyGrid but also from the Shape's right mouse and DSL Explorer.

Tuesday, January 15, 2008

Cleaning "old" DSL Languages

If you are , like me, new to DSLs you will end up creating many DSL projects. ;)

After a while your "New Item" dialog will end up looking really crowded.

Don't ask me why but the "Reset the Microsoft Visual Studio 2008 Experimental hive" option does not seem to work on all cases, and I still have several old dsl languages which won't go away. ( Note: I guess that the reset option by design will not mess us local user's document as explained below)

First, I've tried , with no success, to follow the tip from "El Bruno" (spanish blog) .

What's the solution ?

You need to "remove"all the zip files in the following directories:

C:\Users\\Documents\Visual Studio 2008\My Exported Templates
C:\Users\\Documents\Visual Studio 2008\Templates\ItemTemplates\CSharp\1033
C:\Users\\Documents\Visual Studio 2008\Templates\ItemTemplates\VisualBasic\1033

Note: On every DSLPackage build , a new file .zip will be created and placed on that directory. So before trying to open your DSL make sure you build the project first.

Wednesday, January 9, 2008

Text Templating (tt) : calling custom method

The simplest re-usability technique inside .tt files would be to call a class method.

Below there is an example of how to achieve this:

It's important to notice that this syntax has changed because long time ago you could have seen it as <#! , otherwise look at this old post from Gareth

Text Templating (.tt) Validation

DSL supports a nice validation model for the Domain classes/model.

But what about the Text Templating requirements?

This are validations that apply only to a specific generation task. Let's say if have a property named DotNetType. It could be that this property does not affect generation of [t1] but I need this property for [t2]. For this cases, you will need to somehow validate in the (tt) Template itself.


Note: You could argue (please don't) that the example below is a bad example, I know but there are still some other real cases.

The 'correct' way








I must say that before finding out that I've tried this 2 other options:

  • Raise an exception (hard but work since it's integrated with the Error list as shown below):

  • Just add a comment to the output file (this is not always possible ( example : asp.net template based controls like GridView don't support XML comment inside their tpl tags..)