Tom Fischer

  Home  |   Contact  |   Syndication    |   Login
  21 Posts | 0 Stories | 47 Comments | 0 Trackbacks

News

Archives

Post Categories

.NET Framwork

TFS

Tools

Visual Studio

Monday, February 16, 2009 #

In my current project I have to deal with a reverse proxy environment on production.

Unfortunately you can not debug your application on Production and usually there is no real reverse proxy testing environment available.

To test my WCF-Silverlight application I used Fiddler and custom rules to establish a decent test environment.

 Goal:
To have a reverse proxy behaviour
from
http://mymachine:8888/Default.aspx
to
http://mymymachine:80/testApp/Default.aspx

To add these rules:
Fiddler -> Rules -> Custom Rules

Inside the Java Script function OnBeforeRequest(oSession: Session) add the following lines:

static function OnBeforeRequest(oSession: Session)
{
if (oSession.host.toLowerCase() == "myMachine:8888"){ oSession.host = "mymachine:80";}
if( !oSession.uriContains("testApp/")){ oSession.PathAndQuery = "/testApp" + oSession.PathAndQuery; }

Something interesting to note is the check for testApp.
If you always add the new URI part (what I first did) the MS Ajax engine gets confuesed and adds testApp/testApp to the Resources…

Finaly I can exactly see what my WCF Service sends to the server and where it goes wrong.

That’s it!
Tom


Wednesday, January 28, 2009 #

Finally I had time to start digging into the Entity Framework.

 I found two dnrTV videos which I highly recommend to get started.
http://www.dnrtv.com/default.aspx?showNum=117
http://www.dnrtv.com/default.aspx?showNum=118

 The idea of this and hopefully follow up blogs is to have my own personal Snippets.

Here comes the first one: How to see the generated SQL

Here are the steps:

 • create your Entity Model (.edmx) from your DB and then
• Get an instance of your Context.
• Write the Query in Linq based on your contex
• Call ToTraceString()

Example:

using (var ctx = new MyDBEntities())
{
    var query = from ev in ctx.Events
                select ev;
    var query2 = query as ObjectQuery<Event>;
    Console.WriteLine(query2.ToTraceString());

    foreach (var ev in ctx.Events)
    {
        Console.WriteLine(ev);
    }
}

Tom


Monday, November 24, 2008 #

After being in TFS-Land for a couple of months and celebrating the birth of my second daughter, I finally had time to go back to do some C# coding. Hurray!

Then, I ran into an interesting issue:
When you derive from a class which has an interface implemented you cannot just override the implement methods again. Even if you use the new keyword breaks when you cast the instance to the interface type, you might not achieve the desired result.

Let's look at a quick example and deal with solutions afterwards:

public interface ITom
{
    string IdeaOfTheDay();
}

public class BaseClass : ITom
{
    public string IdeaOfTheDay()
    {
        return "Base Idea";
    }
}

public class DerivedClass : BaseClass
{
    //I have to use the new keyword
    public new string IdeaOfTheDay()
    {
        return "New Idea";
    }
}


DerivedClass d = new DerivedClass();
Console.WriteLine(d.IdeaOfTheDay());
//Writes: New Idea

ITom t = d as ITom;
Console.WriteLine(t.IdeaOfTheDay());
//Writes: Base Idea  -> oops not what I hoped for

Okay this shouldn't have come as a surprise to me. When I thought about it for a second, I realized it is standard polymorphism with contracting to a specific non virtual method. Using interfaces made me forget this for a second.

If we didn't have interaces and we could not change the BaseClass to virtual or make the BaseClass abstract,  we would be done here. Even using the new keyword does not work if we cast to an interface, because the actual contract is with the BaseClass.
Pretty bad when you deal with customer dlls where you cannot modify the source code.

Cheating Polymorphism with Interfaces in an emergency

But with interfaces there is one more thing you can do if you can not change the BaseClass:
Just re-implement the Interface!
public class BaseClass : ITom
{
   
public string IdeaOfTheDay()
    {
       
return "Base Idea";
    }
}

public class DerivedClass : BaseClass, ITom
{
   
//We still need the keyword
   
public new string IdeaOfTheDay()
    {
       
return "New Idea";
    }
}


DerivedClass d =
new DerivedClass();
Console.WriteLine(d.IdeaOfTheDay());
//Writes: New Idea

ITom t = d
as ITom;
Console.WriteLine(t.IdeaOfTheDay());
//Writes: New Idea NOT: Base Idea anymore

Kind of messy but this can be a lifesaver!

Using Polymorphism correctly with Interfaces

But if you can modify the BaseClass you definitely want to use virtual methods.

Even though Interfaces are not virtual by nature, you can still declare the method virtual in your class implementation and make them virtual!
This gives you the best out of both worlds: Polymorphism from Inheritance and Contracting via Interfaces.

public class BaseClass : ITom
{
    public virtual string IdeaOfTheDay()
    {
        return "Base Idea";
    }
}

public class DerivedClass : BaseClass{
    //normal overriding
    public override string IdeaOfTheDay()
    {
        return "New Idea";
    }
}


DerivedClass d = new DerivedClass();
Console.WriteLine(d.IdeaOfTheDay());
//Writes: New Idea

ITom t = d as ITom;
Console.WriteLine(t.IdeaOfTheDay());
//Writes: New Idea NOT: Base Idea anymore

Think about it: An interace is just a contract! Nothing more, nothing less!

Tom


Wednesday, October 29, 2008 #

Yesterday I ran into an interesting problem with TFS 2008 and VS2008.
I had a web application which used a reference to webapp/bin/myLib.dll
 
To get the build scripts running I moved myLib.dll to ../SharedLibrary/myLib.dll.
Then I removed the reference to myLib.dll inside the webapp and added the reference to the new location.
Compiled and it worked fine.
 
Inside the Pending Change Window I saw the that the project files got checked out into edit mode. (as it supposed to)
So I checked them in. But TFS told me that there was no changes and did not check anything in.
 
Of course the build did not work because the server did not get my changes.
So I got latest again and of cause the project reloaded to the original settings.
 
I tried nearly everything:
- Deleted the references
- Restarted VS
- Checked it in.
- Restarted VS
- Added the reference
- Restarted VS
- Checked it in
 
No affect always the same problem.
 
At one point I did the following which finally worked:
- I went into the source control explorer and manually checked the project file out
- Unbound the Project from TFS 
- Opened the project file and changed the the Reference Line manually to:
<Reference Include="myLib, Version=3.0.93.194, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\..\SharedBinaries\myLib.dll</HintPath>
    </Reference>
- Bound the project again
- Checked in
 
I don't know why but the standard way did not work, but finally the build server was able to build it successfully.
 
I have to admit, TFS is great but the 2008 IDE integration has more issues than the 2005 integration...
 
Hope this might also help you
 
Tom

Hi all,

People were asking why I did not post anymore.... Here is the exiting answer:

My wife and me had our second daughter!

Welcome Katja!

We are totally thrilled and sooooo happy!

Tom

 


Tuesday, September 30, 2008 #

After moving a branch from one TFS server to another I got the error:

"The item \$TFSProject\mylocation\myfile.cs does not exist at the specified version".

First I thought the Check in was buggy and went to another machine. And like a miracle it worked there.

Then I googled and found out that this usually relates a messed up workspace.

Especially the following link was very interesting:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2367863&SiteID=1

But this was not my problem.
I had two Visual Studios (2008) open. 
Inside one instance I used the Team Explorer to disconnect from one TFS server and connected to another TFS server without closing the second instance or restarting VS.
I guess the TFS integration in VS got confused and was choking.

So I restarted VS and everything went back to normal.

Sometimes a simple restart does the trick. But at least I learned about how to delete your workspace :-)

Tom


Monday, September 29, 2008 #

I am sorry this is not a C# blog today. I am still in TFS land :-)

Recently I was talking to different people about when to create a new TFS project or reuse an existing one.

Here is what I got out of the conversations:
- Too many projects slow down the server and are hard to maintain.  (Depending on the project type, TFS 2008 has an upper limit of around 200 - 500 projects)

- Security on too many projects can be very hard to maintain (especially keeping track of current permissions, removing expired permissions, etc.)

- Using the built-in TFS Groups in TFS is usually enough. Add NT accounts/groups manually to certain permissions if you have to.

- If the intent of adding a project to TFS is simply to have Source Control, try to stick it into a group specific (generic) TFS project. Move it later if necessary.

- If you don't know exactly how much project management will be included or how big the project will be, stick it in a current TFS project and move it later.

- Moving Source control Items from one TFS project to another works great and is very easy. The history is still searchable.

- Moving Work items is super tricky and should be minimized. See  http://blogs.msdn.com/granth/archive/2008/06/26/how-to-move-work-items-between-team-projects.aspx

- Separating Source Control and Project Management causes more work, because you have to modify the default queries.

- IF you need exclusive permissions for the same user => new TFS project

- IF you need different Template => new TFS projects 
 

See  http://msdn.microsoft.com/en-us/library/ms242894.aspx for a more thorough analysis.

I hope this might help you.
Tom

P.S.: Special thanks to Scott, Robert, and Jeevan for all your input and being a great sounding board!

 


Friday, September 19, 2008 #

This is one I  worked on for a while. The biggest impediment I had was getting the permissions straightened out. Thanks to the help of my team we eventually figured it out.

I won't go into details here about how to use Reporting Services or how to make a report pretty. Instead, I'll give a quick overview of how to pull existing projects from TFS (or, more specifically,  its Reporting Service Engine).

As mentioned, TFS uses SQL Reporting Services for its reports. So all you need is to navigate your web browser to:
http://yourTFSserver/Reports_TFS
If you are lucky enough to have the Content Manager Site role for the whole server, you might see something.

If you only have permissions to a specific TFS project then you better go to your project:
http://yourTFSServer/Reports_TFS/Pages/Folder.aspx?ItemPath=%2f<YOURPROJECT>&ViewMode=List


Then you should see all the Reports available to you. Usually you have enough permission to run them. But if you click on Show Details (in the upper right corner) and then click on edit, or if you try to click on the property tab, you are usually out of luck as a user. You will get an error telling you "Insufficient Permission".... That was my life for a while.

So I was granted the Content Manager role of the specific project but this still did not fix the problem. I was able to upload and run new reports, but not to edit any of them (even the one I created...). Then I was given the admin role for this project and then the site admin role...but still no success.

To make a long story short. You need Content Manager role permission for the whole site to be able to edit a report in a specific project. Content Manager permission for a specific project is not enough. Also Administrator permissions are not enough (which was surprising to me).

Once you know that, then you're dealing with straightforward SQL Report Services. There is good docu out there so I better stop here. Hey it is Friday and my little one is waiting for me at home :-)

I hope this will save you some time and headache.

Tom

P.S.: Thank you Pinal for your help on this one!

 


Wednesday, September 17, 2008 #

How to pull all Pending Changes (Checked Out Items) from TFS 2005 or 2008

This question cost my a day of research, so I thought it is only fair to share my results and to have a look up for myself

There are at least four different options:
- going to SQL directly
- Using the tf.exe tool (great for manual lookup)
- Using the TFS Webservices (painful to use)
- Using the Microsoft.TeamFoundation Libraries, which wrapp the the TFS Webservices   (integrated into .NET)

Going to SQL directly:

See Tad Beaty's Blog

Using the tf.exe

The command line tool does an excelent job, but you have to parse it. Which I don't want to do. But it works great

C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE>tf status /s:<TfsServer>  /recursive /user:* /format:detailed

Get more infos on MSDN:
http://msdn.microsoft.com/en-us/library/cc31bk2e(vs.80).aspx

The TFS Webservices

http://blog.phase2int.com/?p=141  has a list of all Availalbe Webserices exposed by TFS.

What I read is that MS disencourages you to use these directly. MS advises you to use the API (next chapter). But if you need remote access then this is your best shot.

 If you don't need remote access you might want to consider the next option.

The Microsoft.TeamFoundation Libraries

I found multiple names for them: TFS SDK, TFS object access, etc.
But in the end they all refer to the MS dlls, which are used to access the TFS Webservices:
- Microsoft.TeamFoundation.dll
- Microsoft.TeamFoundation.VersionControl.Client

They can be found in C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies

Below is the code you can use to pull all the changes now:

using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;

public static void GetPendingChanges(string tfsServer)
{
 //connection to TFS Version Control    
 TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer("<YOUR tfsServer>");
 VersionControlServer vcs = (VersionControlServer)tfs.GetService(typeof(VersionControlServer));

 //pulling the pending changes    
 PendingSet[] pending = vcs.GetPendingSets(new string[] { "$/" }, RecursionType.Full);
 
 //start printing them on the screen:    
 foreach (var item in pending)
 {
    Console.WriteLine("\n--------------------------------");
    Console.WriteLine("User: " + item.OwnerName);
    if (item.PendingChanges != null)
    {
        Console.WriteLine("Number of Checked Out Files: " + item.PendingChanges.Length.ToString());
        Console.WriteLine("Files:");
        foreach (var change in item.PendingChanges)
        {

           Console.WriteLine("-File: " + change.ServerItem);
           Console.WriteLine("-- ChangeType: " + change.ChangeTypeName);
           Console.WriteLine("-- Checked Out: " + change.CreationDate.ToString());
           Console.WriteLine("-- Local file" + change.LocalItem);
        }
    }
 }
}

Of course this is not even the tip of the iceberg. There is so much more in the Libraries. I recommend you check out MSDN for the TFS SDK.

There might be more on the blog in the future :-)

Tom


Monday, September 15, 2008 #

Using() Statement in 3 seconds and a bug in Reflector

The boring, known accross the board definition from the MSDN site:
Defines a scope, outside of which an object or objects will be disposed

The more interesting definition from Tom:
The using() Statement generates a try{} finally{ //virtual call of the dispose method } block with null check!

Let's take a deeper look.

Let's write two test methods first:

//Testmethod for Using   
public static void UsingTest()
{
    using (SqlConnection con = new SqlConnection())
    {
        con.ConnectionString = "Test Connection";
    }
}

//TestMethod for try finally
public static void TryFinallytest()
{
    SqlConnection con = new SqlConnection();
    try
    {
        con.ConnectionString = "Test Connection";
    }
    finally
    {
        con.Dispose();
    }
}

Note: The TryFinallyTest() method has no null check inside the finally block. This means in case con is null the function would throw a Null Reference Exception. The UsingTest() method does not.

When you compile both methods and look at them disambeled in Reflector they both look exatly the same:

public static void UsingTest()
{
    using (SqlConnection con = new SqlConnection())
    {
        con.ConnectionString = "Test Connection";
    }
}

public static void TryFinallytest()
{
    using (SqlConnection con = new SqlConnection())
    {
        con.ConnectionString = "Test Connection";
    }
}

But looking at the IL (see below) reveals a very important difference:
-  Frist both get translated into a try{} finally {} block. (see IL code below). This is what we expected
The using(){} statement adds a null check before calling the dispose method inside the finally.
-  The compiler did not add a null check for the TryFinallyTest method (as intented)

The Problem:
The TryFinallyTest method gets disasembeld from IL into C# (or VB) by using a using() statement .
This is not correct because a using() statement has a null check before calling the dispose() method.
This means the disasembled C# code does not relfect the IL correctly.

Here is the IL code for the UsingTest() method:

.method public hidebysig static void UsingTest() cil managed
{
    .maxstack 2
    .locals init (
        [0] class [System.Data]System.Data.SqlClient.SqlConnection con,
        [1] bool CS$4$0000)
    L_0000: nop 
    L_0001: newobj instance void [System.Data]System.Data.SqlClient.SqlConnection::.ctor()
    L_0006: stloc.0 
    L_0007: nop 
    L_0008: ldloc.0 
    L_0009: ldstr "Test Connection"
    L_000e: callvirt instance void [System.Data]System.Data.Common.DbConnection::set_ConnectionString(string)
    L_0013: nop 
    L_0014: nop 
    L_0015: leave.s L_0027
    L_0017: ldloc.0     
    L_0018: ldnull  
    L_0019: ceq 
    L_001b: stloc.1 
    L_001c: ldloc.1 
    L_001d: brtrue.s L_0026    //Nullcheck
    L_001f: ldloc.0 
    L_0020: callvirt instance void [mscorlib]System.IDisposable::Dispose()  //dispose call
    L_0025: nop 
    L_0026: endfinally 
    L_0027: nop 
    L_0028: ret 
    .try L_0007 to L_0017 finally handler L_0017 to L_0027
}

Note: L_001d: brtrue.s perfoms the null check. In case con is null it jumps directly to the endfinally. This means in case con is null there is no Null Reference Exception

Here is the IL code for the TryFinallyTest method:

.method public hidebysig static void TryFinallytest() cil managed
{
    .maxstack 2
    .locals init (
        [0] class [System.Data]System.Data.SqlClient.SqlConnection con)
    L_0000: nop 
    L_0001: newobj instance void [System.Data]System.Data.SqlClient.SqlConnection::.ctor()
    L_0006: stloc.0 
    L_0007: nop 
    L_0008: ldloc.0 
    L_0009: ldstr "Test Connection"
    L_000e: callvirt instance void [System.Data]System.Data.Common.DbConnection::set_ConnectionString(string)
    L_0013: nop 
    L_0014: nop 
    L_0015: leave.s L_0021
    L_0017: nop 
    L_0018: ldloc.0   //it loads con and calls directly dispose in the next line. No null check
    L_0019: callvirt instance void [System]System.ComponentModel.Component::Dispose()
    L_001e: nop 
    L_001f: nop 
    L_0020: endfinally 
    L_0021: nop 
    L_0022: ret 
    .try L_0007 to L_0017 finally handler L_0017 to L_0021
}

Note: Inside the the finally block the IL loads con on the Excution Stack and calls dispose() directly without a null check. In case con is null, an Null Reference Exception is thrown.

 

So, what to use? Using() or try{} finally{}?
Well, usually I would recommend using Using(), so you don't have to remember the null check.
But if you have multiple using inside eachother I would rather use one try{} finally{}.

If you don't know (or if you are too lazy to check)  if your object implements IDisposable you can always use the following pattern to be on the save side:

public static void ObjectAsDispose(SqlConnection con)
{
    using (con as IDisposable)
    {
        con.ConnectionString = "Test Connection";
    }
}

I hope you enjoyed this one again.

Tom

P.S.: Thanks Ian for reminding me to add the safty pattern for using!