Monday, November 14, 2011

Debugging T4 Templates

T4 templates are a great way to write code that writes code.  Huh?  I'm not going to go into it here, so if you want more information, see Scott Hanselman's post on T4 templates, as well as Oleg Synch's posts.

One of the pain points when writing T4 templates is with debugging them.  Sometimes you'll save a .tt file and get some obscure error message that is impossible to figure out, and you have no clue what part of your T4 file is messed up.

It is possible to debug them, and Oleg provides some great pointers.  Here is my summary of how to get it working:


1. Make a registry edit as follows:
     If you're on a 32 bit OS:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\DbgJITDebugLaunchSetting - Set to 0x2
      If you're on a 64 bit OS:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\DbgJITDebugLaunchSetting - Set to 0x2
(if you don't make this change, you can get debugging to work, but Visual Studio will be hung after you finish debugging)

2. Reboot
(otherwise the registry change won't get picked up)

3. Set debugging to true at the top of your .tt file:
<#@ template language="C#v3.5" debug="True" #>

4. Force the debugger to launch
System.Diagnostics.Debugger.Launch();


5. Put breakpoints in your code
System.Diagnostics.Debugger.Break();

6. Make a change to and then save your T4 file


When you save or run your T4 file, it should now pop up a window asking you if you want to debug it using a new instance of Visual Studio.  This second instance should allow you to step through the execution of the T4 file so that you can see where your code is broken.

Tuesday, October 11, 2011

Constructor vs. ClassInitialize

I recently ran across some code in a test class where I saw that the class was initialized in a constructor rather than in a method with the ClassInitialize method, and it made me wonder - what's the difference?

The goal is that we have a test class with several test methods, and we have some initialization code that is common to all of the test methods.  We want the initialization code to run only once for the entire set of tests, not once per test.

One way to do this is to put the initialization code in the constructor, like this:

        public MyTestClass()
        {
            var x = 5;
            x.Should().Be(4);  // Fluent Assertions
        }

Another way is to create a static method with the ClassInitialize attribute, like this:

        [ClassInitialize]
        public static void Init(TestContext testContext)
        {
            var x = 5;
            x.Should().Be(4);  // Fluent Assertions
        }

So what's the difference?

Wednesday, July 20, 2011

Sendoid

I've been keeping an eye out for a simple way to share a large file (1-5 GB) to another person over the internet privately, and I finally found something that I like.   Sendoid.

The uploader and downloader can use it either from the web page or from the client app they provide.  However, if you use the client app you get the ability to resume a transfer in the event that it's interrupted, which is very important for large files.


You can have multiple people downloading from you at the same time, and when you're done, remove the file from the list or close the app.  Very simple, no registration or signup required.

Thanks, Sendoid!


http://sendoid.com

Wednesday, June 1, 2011

Postback Failing

I ran into a strange problem this week on a client's .Net site I was working on.  There were two pages where postbacks were being completely ignored.  If you clicked on anything that required codebehind or postbacks to work, such as the login/logout button, the save button, etc., an HTTP POST would occur (verified by Firebug), but the server would ignore the POST and serve up the page as if you did a GET.

Interestingly, it worked great on IE and Safari, but failed on Chrome and Firefox.  What was even stranger was that everything worked properly when debugging in Visual Studio, but the failure occurred when the site was deployed to IIS.

So the failure occurred only when running Firefox or Chrome against IIS.  The same website with IE and Safari worked great, and the same website on Cassini worked great in any web browser.

Hmm...

I ended up using WinDiff to compare the HTML output differences between what was served up from Cassini (Visual Studio during debugging) and IIS.  There was one line that was different:

On Cassini:
<form name="aspnetForm" method="post" action="/default.aspx?" id="aspnetForm">

On IIS
<form name="aspnetForm" method="post" action="/" id="aspnetForm">

Monday, May 23, 2011

Sharepoint 2010 Custom Workflow Activites

(If you're impatient, you can see the code before reading the article)

Sharepoint has a workflow engine, and you can develop workflows for Sharepoint using either Sharepoint Designer or Visual Studio.  Today I'm going to focus on workflows that are created using Sharepoint Designer.  A step in a workflow, such as "Copy item from List A to List B", is called an Activity.

Sharepoint Designer comes with a number of activities out of the box, but you can use Visual Studio to create custom activities that are surfaced to Sharepoint Designer.  For example, if you saw the existing workflow "Copy item from List A to List B", but it wasn't quite what you wanted, you could create a custom activity for "Copy item from List A to List B and List C", and that activity would then show up in Sharepoint Designer when creating a workflow.

Lets dig into how you can create a custom activity for Sharepoint Designer using Visual Studio.