Reduce your XAP file size in seconds

October 31, 2008

Want to make your Silverlight XAP packages smaller? It couldn’t be easier!

Extract the XAP file (rename to .ZIP and use any extractor). Then… re-compress it using a good ZIP tool, like WinRAR.

Third party zippers are far more efficient than the one built in to Visual Studio.

In my trial, I got a 280k file down to 220k!


Silverlight and Windows Live ID Video

August 13, 2008

Complementing my earlier post here is a video cast of the same content.

It’s available in browser and in two download formats (WMV and iPod).

Check it out here.

NOTE: In the video I refer to Windows Live ID and services like it as delegated authentication providers… this isn’t 100% correct. Delegated authentication is a part of Windows Live ID. For more information see here.


Client Side Template AJAX Control

June 19, 2008

Since the release of ASP.NET AJAX it’s been relatively easy to update portions of a page with new data from the server without performing a full page post back.

Place any grid in an UpdatePanel and voila you have a nice AJAX style grid… but is this really a good thing? Sure it’s easy, but that doesn’t make it “good”. UpdatePanels are great for small chunks of data, but not so good for larger amounts of data (like grids etc).

How do you fix this problem? Well, you could ask the server for some JSON and parse it yourself, loop through a set of elements and update them using JS. This method performs very well… but comes at the cost of difficulty and code complexity. It would also be hard to maintain.

What about a way to get the best of both worlds. Client side controls that use JSON data from the server (so no markup is sent to client after initial load) and easy to use!

Thanks to Nikhil Kothari I had a cool idea to allow an easy implementation of client site templating.

<Sample Code>

http://www.webjak.net/files/FileDetail.aspx?fileId=af820273-6a56-47a2-8f70-eb9dea4a4f34

</Sample Code>

<Live Example>

http://dev.webjak.net/ClientTemplateControlExample/

</Live Example>

Check out the example site! How fast is it?? Load up Firebug or something and test it out for yourself!

Introducing the ClientTemplateControl

The ClientTemplateControl is an ASP.NET AJAX Client Control. It works very similar to the DataList in ASP.NET. Create an item template with markup and bind attributes to data elements. Then assign a datasource to the control and bind it. The control will then take care of iterating through the data source, repeating the item template for you.

When you reload the data, for example after paging – the ClientTemplateControl detects that the elements are already added to the page and REUSES THEM! That’s right, it uses the template to whip through and only update their attributes etc! This means no setting of innerHTML etcetera on a refresh! Well, except where your template “bindings” set innerHTML (like in spans etc).

This HTML DOM reuse means that there is absolutely no flicker either… and there is no DOM rendering time on large lists… just the time it takes to go through and update attributes etc… this is very fast.

To bind an attribute, use the { and } to delineate a bound attribute. The control detects { and compiles the attribute text in to a function, which is then run, passing in the current data context (the current row from the data source and a few other parameters).

Example

This will write out the value in dataContext.Surname into the title:

<span title="”{return">Some Span</span>

To set innerHTML etc, which don’t have attributes you can use the “this” JavaScript keyword.

Example

This will write out the value in dataContext.Surname into the title and innerHTML:


<span title="”{this.innerHTML"></span>

You might want to alternate color between odd and even rows.

Example

Note here I am using title to set the style. You could use any parameter you like. Note also that title above does not return anything. This is fine, and will result in an empty title attribute.

<div title="{this.style.backgroundColor=pageRowIndex % 2 == 0?'lightblue':'#eeeeee';}">rest of the template</div>

. pageRowIndex is another parameter passed into the functions by default.

There is a special circumstance when working with anchors and images. “src” and “href” don’t like the special “{}” syntax. You can still set href and src, just do it using the “this.” syntax.

Example

<img style="border:none;" title="{this.src='ImageLoader.ashx?id=' + dataContext.ProductID;}" />

Getting data in

Providing data to the control is very easy. You may want to get some JSON data from a webservice and bind to the control in pages.
Note: Pagination is not handled by the control, so only return the data for a single page at a time from the server.

E.g. getting data from a AJAX-enabled WCF service is easy!

AdventureWorksService.GetProducts(page,$get("pageSize").value,endGet);

function endGet(result)
{
	c.set_itemsSource(result);
	c.dataBind();
}

How easy is that?!

The “result” variable above lives in the WCF service as List<AWProductBusinessObject>, thus serialising as an array of AWProductBusinessObject to JSON. AWProductBusinessObject looks like this:


[DataContract]
public class AWProductBusinessObject
{
	 [DataMember]
	 public int ProductID { get; set; }
	 [DataMember]
	 public string Name { get; set; }
	 [DataMember]
	 public string ProductNumber { get; set; }
	 [DataMember]
	 public string Color { get; set; }
	 [DataMember]
	 public decimal StandardCost { get; set; }
	 [DataMember]
	 public decimal ListPrice { get; set; }
	 [DataMember]
	 public decimal? Weight { get; set; }
	 [DataMember]
	 public int DaysToManufacture { get; set; }
	 [DataMember]
	 public DateTime SellStartDate { get; set; }
	 [DataMember]
	 public DateTime ModifiedDate { get; set; }
	 [DataMember]
	 public Byte[] SmallImage { get; set; }
	 [DataMember]
	 public Byte[] LargeImage { get; set; }
}

I’ll leave the rest of this detail to the sample code.

Something interesting in the control is that it caches the evaluated functions from the “bindings” so they are only evaluated on the creation of the first instance of the template on the first page. That’s right, only the very first record on the first page has this overhead, all other items on that page (say you have 10 records, 9 will use the cache) and all other page refresh items (10 from 10 on subsequent refreshes) will use the cache and be very fast.

Note: Code does not check for the last page in the data… it will just keep paging into oblivion :)
Note: You may have noticed every time I write “bind” or “binding” it’s in quotes. This is because it’s not real binding… it just chose to call it that because it was familar :)
Note: This has no relation to the ASP.NET AJAX Futures databinding feature.
Note: This is by no means W3C compliant – so don’t bother commenting about it – unless that is you can find a way to upgrade it to make it W3C compliant :)
Note: This code has been tested with Firefox 2 and 3, Opera 9.5, IE 7 and Safari 3.1.2.


UpdatePanel Trigger Chainer

May 2, 2008

I present a little JavaScript class I wrote which allows you to queue up a list of UpdatePanel trigger events, which will each be executed in order, one after the other when the previous update finishes. For example, you may want to refresh UpdatePanel1 then UpdatePanel2 and so on.

With a bit of ingenuity you could string together updates in such a way to improve user load times and UX.

Some ideas may be:

  • Load sections of the page as the scroll into view.
  • Load panels in tabs one at a time. This would be good because the first tab would load very quickly, the rest would load in the background whilst user has attention on the first tab.
  • Pre-load other data in the background – e.g. Load a list of images, then background-load their detail into hidden DIV elements. Show the hidden div when user clicks.
  • A random looking recursively loading control that shows date times with random colours. Err… see an example of the UpdatePanelEx.Chainer class here: http://dev.webjak.net/updatepanelchainerexample/.

Download the class and example site here: UpdatePanelChainer.zip

I’m sure there are heaps of cool things you could do with this… it’s basically a great way of chaining up asynchronous post backs that run after the main page has loaded.

It works by queuing up the names of items in the page which can trigger an asynchronous postback, like buttons (hidden or visible) and UpdatePanels themselves.

Triggers may be added at any time, even if an UpdatePanelEx.Chainer object is already processing other items in the queue. Triggers may be added from both client side and from server side by filling a property on the UpdatePanelEx.Chainer default object (with a JSON array – example provided).

The UpdatePanelEx.Chainer creates a default known instance on startup so server side code as something to send trigger additions to, but you may create as many instances of the class yourself as you like. UpdatePanelEx.Chainer will continue to operate when multiple instances are attempting to update at once – they will each enter a one second timeout before retrying to initiate an async postback.

Usage is quite simple:

var chainer = new UpdatePanelEx.Chainer(["ItemOne", "ItemTwo"], true);

The first parameter is an array of items to update. These must be the full client ID, separated by the $ sign – e.g. MyControl$Button1.
The second parameter sets if the UpdatePanelEx.Chainer should automatically start posting back when items are added.

Items may also be added by calling the addTrigger method:

//Note: MyControl$Button1 is not required when the items are in the base page (only when the triggers are in a user control or other control container)
chainer.addTrigger("MyControl$Button1");

Full Property List

  • beginUpdating() – start the post backs. Use this when beginUpdateOnAddTrigger (set by property below, or in constructor) is set to False to being the post backs.
  • set_beginUpdateOnAddTrigger(boolean) – When set to true, post backs will automatically commence when the next item is added to the triggers array.
  • addTrigger(triggerName) – Add a trigger to the queue.
  • set_jsonUpdateTriggerList(jsonArrayString) – Adds a JSON array of objects to the trigger queue. More on this below.

NOTE: There are some properties and functions in the class beginning with _. These are not intended to be called directly – doing so may cause unpredictable results.

Updating the trigger list from the server

Updating the trigger list from the server is quite simple. Either you can use the default known “static” object called ChainerStatic, or you can use your own instance of the UpdatePanelEx.Chainer class – it doesn’t matter as long as you know the name.

System.Web.Script.Serialization.JavaScriptSerializer ser = new System.Web.Script.Serialization.JavaScriptSerializer();
string[] updates = { string.Format("{0}$btnHidden", this.ClientID.Replace('_', '$')) };
string json = ser.Serialize(updates);
ScriptManager.RegisterStartupScript(this, this.GetType(), "AddJsonTriggers_" + this.ClientID, string.Format("ChainerStatic.set_jsonUpdateTriggerList('{0}');", json), true);

This sample code is from the recursive random colour example app linked above. The full source code is available a the bottom of this article.

The first line creates a JavaScriptSerializer object which can be used to serialise .NET objects into a JSON notation string.
Next we create an array of names that are the triggers for the updates. In this example we are only adding one object to the array, but you could add as many as you like. Note here how the client ID is appended to the front of the name, and the _ are converted to $.
The next line serialises the object to the JSON string. This string will be set into the set_jsonUpdateTriggerList property on the line after using ScriptManager.RegisterStartupScript.

About the Sample

Link: http://dev.webjak.net/updatepanelchainerexample/

The sample app includes a WebUserControl called DataPiece which queues its own asynchronous update on initial load. Variables are set into the view state to ensure it only does this once. When the queue reaches the control, the post back is fired on the button. This creates two more instances of the control and adds them to the two panels (thus repeating the process). There is a counter to ensure this only happens four times.

The Default.aspx page then adds two of these Data Piece controls on to itself, kicking off the recursive control add processes.

Chainer class listing and explanation


Type.registerNamespace('UpdatePanelEx');

UpdatePanelEx.Chainer = function(updateTriggers, beginUpdateOnAddTrigger)
{
    //construct some initial values
    this._updateTriggers = updateTriggers;
    this._initialised = false;
    this._beginUpdateOnAddTrigger = beginUpdateOnAddTrigger;
    this._doing = false;
    this._jsonUpdateTriggerList = "";
}

First a new class is created and some constructor values are set. This class accepts two parameters: an array of items to add to the trigger collection and a boolean which sets the beginUpdateOnTrigger property.


UpdatePanelEx.Chainer.prototype = {
    _init : function()
    {
        if(!this._initialised)
        {
            //hook up the events, ensure this only happens once
            this._initialised = true;
            var prm = Sys.WebForms.PageRequestManager.getInstance();
            var callBackDelegate = Function.createDelegate(this, this.endRequestHandler);
            prm.add_endRequest(callBackDelegate);
        }
    },

_init is automcatically called the first time doUpdate is called. This function hooks up the event which instructs the chainer when the previous update has completed. Take note of the call to Function.createDelegate(). This method ensures that the scope of the callback is set to “this”… meaning the callback can access all the local members as you would expect. Without this the callback would have another scope (probably the event handler or something) and you would not be able to call any methods on the chainer class.


    endRequestHandler : function(sender, args)
    {
        //continue the update chain
        this.doUpdate();
    },    

This function is called when an asynchronous postback has completed. It calls the doUpdate() method to continue on with the chain. Note that without the Function.createDelegate call above, this.doUpdate() would not be available.


    doUpdate : function()
    {
        if(!this._initialised)
        {
            this._init();
        }
        this._doing = true;
        //while there are triggers left, continue the update process
        if(this._updateTriggers.length > 0)
        {
            var prm = Sys.WebForms.PageRequestManager.getInstance();
            if(prm.get_isInAsyncPostBack())
            {
                var pnl = this._updateTriggers[0];
                Sys.Debug.trace("Update wait: " + pnl);
                this._doUpdateWait();
                return;
            }
            var panel = this._updateTriggers[0];
            Array.removeAt(this._updateTriggers, 0);
            prm._doPostBack(panel, '');
        }
        else
        {
            //if there are no triggers left, then end the process
            this._doing = false;
        }
    },

This function forms the central part to the chainer. First it checks if the init function has been run. The next part only runs if there are items in the _updateTriggers array. Next the PageRequestmanager object instance is populated in to the prm variable and a check is performed to see if there is already an asynchronous post back in operation. If there is then the _doUpdateWait() method is called. This provides some kind of concurrent chainer object protection.
If all is clear then the system will grab the next object from the _updateTriggers array, then remove it from the array and call the PageRequestManager’s _doPostBack method. The trigger array acts as a FIFO stack… first in first out (this is achieved by getting the first object out).


    _doUpdateWait : function()
    {
        //this performs some basic sychronisation between two or more Chainers running at one time
        var doUpdateDelegate = Function.createDelegate(this, this.doUpdate);
        window.setTimeout(doUpdateDelegate, '1000');
    },

This function is called when there was already an asynchronous post back running. It sets a one second timeout before retrying. Note another call to Function.createDelegate to ensure the callback has the correct scope.


    beginUpdating : function()
    {
        //_doing ensures we dont accidentally kick off two update chains.
        if(!this._doing)
        {
            this.doUpdate();
        }
    },

This function kicks off the chain of asynchronous post backs. This method should be used over the doUpdate() method as it checks first if this class is already running the update chain.


    addTrigger : function(triggerName)
    {
        //add more triggers to the update array
        Array.add(this._updateTriggers, triggerName);
        if(this._beginUpdateOnAddTrigger)
        {
            this.beginUpdating();
        }
    },

This function allows the addition of a trigger at any stage. If beginUpdateOnAddTrigger is set to true then the update chain is started.


    set_beginUpdateOnAddTrigger : function(autoBeginMode)
    {
        this._beginUpdateOnAddTrigger = autoBeginMode;
    },

Turns the auto start when add trigger on or off.


    set_jsonUpdateTriggerList : function(jsonString)
    {
        //this method handles adding triggers that have been sent from server
        var serializer = Sys.Serialization.JavaScriptSerializer;
        //convert the serialised json data into a proper array
        var arrAdd = serializer.deserialize(jsonString);
        //create a little delegate to pass into the Array.forEach below. There are easier ways, but this is good practice :) 
        var arrayAdd = Function.createDelegate(this, function(item) {
            Array.add(this._updateTriggers, item);
            Sys.Debug.trace ("Added: " + item);
            });
        Array.forEach(arrAdd, arrayAdd);
        if(this._beginUpdateOnAddTrigger)
        {
            this.beginUpdating();
        }
    }

This method is used to add items to the trigger array from the server side. First a serializer object is created which is used to take the input JSON string and convert it to a JavaScript object. Next the array that was in the JSON string is copied into the triggers array. Note how I decided to use a function delegate and the Array.forEach method… there are simpler ways, but I wanted to try this out as I had not used it before :) . Once again, if beginUpdateOnAddTrigger is set then this method will start the update chain process.

}

UpdatePanelEx.Chainer.registerClass('UpdatePanelEx.Chainer');

var ChainerStatic = new UpdatePanelEx.Chainer([], true);

The last part here registers the class with the ASP.NET AJAX type system and creates a known “static” type object mainly for use from the server (a known object is required from server to update using the set_jsonUpdateTriggerList function.

Known Issues

  • I noticed that the progress templates for the panels aren’t working – I will investigate and update the post.
  • Refreshing the sample app will not cause the updates to start again due to a bug where the viewstate isnt cleared out :)

So there you have it.

Questions and comments are welcome as always.
This work is licenced under a Creative Commons Licence.


UpdatePanel Addiction

April 30, 2008

Update panel addiction is a nasty thing. Projects start, it’s decided they are to be “Ajaxified” – the answer: chuck in 50 million update panels to do the trick. The more the better is the general principal, as this means there are smaller sections of the page being updated. UpdatePanels are designed to be used to update small portions of the page – the less content encompassed by an UpdatePanel, the better.

With a sufficiently advanced application the need may arise to refresh update panels from other update panels by calling the Update() method.

One problem that can occur in such advanced applications (especially those which use some kind of framework for events and control instantiation and such) is that slowdowns can be caused when update panel refreshing is too liberal. Perhaps only a small section of the page should be being updated, but for some reason it’s parent UpdatePanel is also refreshing, or there are simply too many updates per post back. Slowdowns can also be caused when large amounts of content, like in an un-paged grid or table of data is sent back to the client for rendering… the delays are not only in the transmission of the data to client but also while the browser is rendering the new data (especially when tearing down the existing DOM elements, more on that in another post).

What ever the case, sometimes it’s nice to see what is going on under to hood during an async postback.

Ajax Response

The ASP.NET Ajax system sends back async updates as special tokenised text. E.g.

247|updatePanel|UpdatePanel1|
askdljfjlkasdf aklsdflkasfjlkadjkldas
<br /><br /><span id="Label1">29/04/2008 6:40:36 AM</span><br />
<input type="submit" name="Button1" value="Button" id="Button1" />
|128|hiddenField|__VIEWSTATE|/asdfasdf|48|hiddenField|__EVENTVALIDATION|/wEWAgLWzvmRBwKM54rGBpmraqo+tCbnoafT7bqYDaCZ2bH5|
0|asyncPostBackControlIDs|||0|postBackControlIDs|||13|updatePanelIDs||tUpdatePanel1|
0|childUpdatePanelIDs|||12|panelsToRefreshIDs||UpdatePanel1|2|asyncPostBackTimeout||90|12|formAction||Default.aspx|13|pageTitle||Untitled Page|

To view the tokenised output of your page, try something like the following code in your page:


protected override void Render(HtmlTextWriter writer)
{
   ScriptManager sm = ScriptManager.GetCurrent(this);
   if (sm == null || !sm.IsInAsyncPostBack)
   {
      //this is a normal postback
      base.Render(writer);
   }
   else
   {
      //this is an async post back (partial render) so lets see what is going to be output
      HtmlTextWriter textWrite = new HtmlTextWriter(new System.IO.StringWriter());
      base.Render(textWrite);
      //have a look at content variable after the next line has run
      string content = textWrite.InnerWriter.ToString();
      writer.Write(content);
   }
}

The basic breakdown of this output is: [SectionLength]|[TokenCommand]|[TargetID]|[Content]

As you can see there are various commands. Some of the more interesting ones are:

  • updatePanel – refreshes the target UpdatePanel with the new content. UpdatePanels are simply either DIVs or SPANs (depending on the the RenderMode attribute is set to Block or Inline) in the final rendered content – so this content will just overwrite the existing content.
  • hiddenField – update any field’s value with the new value here
  • expando – update any element’s attribute with a new value
  • pageTitle – updates the page title in the browser window
  • focus – after the render has completed this control will be given focus.

You can find lots more information and some cool tricks on Siderite Zackwehdex’s blog here: http://siderite.blogspot.com/2007/05/messing-with-updatepanel-to-speed-up.html.

Browser Add-ins

There are a number of ways to view the innards of a server round trip. For starters, every developer should have these tools: Firebug for Firefox and Web Development Helper for IE – you do test in at least these two browsers right?

Web Development Helper (Internet Explorer only) (by Nikhil Kothari of ASP.NET team fame) allows very close inspection of the AJAX response. Grab the installer from here: http://www.codeplex.com/webdevhelper.

Start the add-in by selecting View -> Explorer Bar -> Web Development Helper.

Fire up your latest AJAX based work of art, and select the “Enable Logging” checkbox. Perform an action that will kick off an UpdatePanel refresh, then double click the response in the logging window. Select the Response Content tab from the bottom section of the popup and voila – you have your AJAX information. Fold out updatePanel and select one of the items – you will see the content that was sent back to the client.

WebDevHelperSShot

Trace debugging UpdatePanel movements

In Visual Studio, it’s sometimes nice to write out some custom debugging information into the output window to get a broader view of what is happening with your program. Previously this has not been straight forward to achieve with client script (often JS debug sessions ended in “alert” style debugging) – but with the MS AJAX Client Library it’s a breeze.

Using the Web Development Helper add-in is a bit like bringing up a quick watch every time you want to view the information… but what if you want to survey an application over a period of time or you have a lot of action going on and want to see what’s happening without having to stop each time to bring up the debug results.

Luckily you can hook into the PageScriptManager object to receive notifications when the AJAX framework is doing things – then show some information about what is going on in the Visual Studio output window (and in the Script Console window in Web Development Helper).

Here is something I have put together for you to try.

First create a new JS file in your project and place the following code in it:


var updatePanelHook =
{
    initialised : false,
    init : function()
    {
        if (!this.initialised)
        {
            //hook up to the various page loading events to provide extended update panel functionality
            var prm = Sys.WebForms.PageRequestManager.getInstance();
            prm.add_pageLoading(pageLoadingHandler);
            this.initialised = true;
        }
        function pageLoadingHandler(sender, args)
        {
            var arr = args.get_panelsUpdating();
            for(var i =0; i< arr.length;i++)
            {
                var updatedPanel = arr[i];
                Sys.Debug.trace(String.format("Updated: {0}", updatedPanel.id));
            }
        }
    }
}

if (typeof(Sys) != 'undefined' )
{
    Sys.Application.notifyScriptLoaded();
}

Ensure the script is included in your page (or master page etc). It's best to use the ScriptManager object to do this:

Place the following code in your page to kick off the init function:


      updatePanelHook.init();

NOTE: The init() function checks that it has not already performed initiation, because the updatePanelHook variable and associated event subscriptions will persist though partial updates.

In Web Development Helper, switch to the Script Console view by clicking on HTTPLogging and selecting the option from the drop down.

Perform an action that causes an UpdatePanel post back and you will see the results of you postback in the script window. If you have run your project by debugging from Visual Studio, you will also see the results in the output window there. Slot that into a larger ASP.NET AJAX based app and it should assist you figuring out what your app is doing under the hood!

An interesting point here is that the objects in the “arr” variable in this code are DOM elements (DIVs and SPAN’s)… so you can do all sorts of things with them if you like.

This process helped me figure out why a large commercial web app I was working on was slowing down, and with some ingenuity I managed to get the number and size of the UpdatePanel requests right down, gaining more than a 2x speed improvement across the entire app.

One other small point: when performing HTTPLogging in Web Development Helper, keep an eye on the Response Size column… obviously the smaller you can get your responses the better.


PowerCommands for Visual Studio 2008

March 14, 2008

PowerCommands adds some great functionality to Visual Studio 2008 – I strongly recommend you install this. Navigate to http://code.msdn.microsoft.com/PowerCommands and click on the Releases tab to download. The Collapse Projects command is worth the download alone!

As a Readify colleague pointed out it’s very similar in functionality to CoolCommands for Visual Studio 2005 (http://geekswithblogs.net/brians/archive/2007/03/04/107922.aspx).

PowerCommands Feature List

(This is ripped from the PowerCommands MSDN site)

Collapse Projects
This command collapses a project or projects in the Solution Explorer starting from the root selected node. Collapsing a project can increase the readability of the solution. This command can be executed from three different places: solution, solution folders and project nodes respectively.

Copy Class
This command copies a selected class entire content to the clipboard, renaming the class. This command is normally followed by a Paste Class command, which renames the class to avoid a compilation error. It can be executed from a single project item or a project item with dependent sub items.

Paste Class
This command pastes a class entire content from the clipboard, renaming the class to avoid a compilation error. This command is normally preceded by a Copy Class command. It can be executed from a project or folder node.

Copy References
This command copies a reference or set of references to the clipboard. It can be executed from the references node, a single reference node or set of reference nodes.

Paste References
This command pastes a reference or set of references from the clipboard. It can be executed from different places depending on the type of project. For CSharp projects it can be executed from the references node. For Visual Basic and Website projects it can be executed from the project node.

Copy As Project Reference
This command copies a project as a project reference to the clipboard. It can be executed from a project node.

Edit Project File
This command opens the MSBuild project file for a selected project inside Visual Studio. It combines the existing Unload Project and Edit Project commands.

Open Containing Folder
This command opens a Windows Explorer window pointing to the physical path of a selected item. It can be executed from a project item node

Open Command Prompt
This command opens a Visual Studio command prompt pointing to the physical path of a selected item. It can be executed from four different places: solution, project, folder and project item nodes respectively.

Unload Projects
This command unloads all projects in a solution. This can be useful in MSBuild scenarios when multiple projects are being edited. This command can be executed from the solution node.

Reload Projects
This command reloads all unloaded projects in a solution. It can be executed from the solution node.

Remove and Sort Usings
This command removes and sort using statements for all classes given a project. It is useful, for example, in removing or organizing the using statements generated by a wizard. This command can be executed from a solution node or a single project node.
Note: The Remove and Sort Usings feature is only available for C# projects since the C# editor implements this feature as a command in the C# editor (which this command calls for each .cs file in the project).

Extract Constant
This command creates a constant definition statement for a selected text. Extracting a constant effectively names a literal value, which can improve readability. This command can be executed from the code editor by right-clicking selected text.

Clear Recent File List
This command clears the Visual Studio recent file list. The Clear Recent File List command brings up a Clear File dialog which allows any or all recent files to be selected.

Clear Recent Project List
This command clears the Visual Studio recent project list. The Clear Recent Project List command brings up a Clear File dialog which allows any or all recent projects to be selected.

Transform Templates
This command executes a custom tool with associated text templates items. It can be executed from a DSL project node or a DSL folder node.

Close All
This command closes all documents. It can be executed from a document tab.


Alternative to built in compare and merge tools in TFS, Tortoise SVN and more

March 13, 2008
KDiff3 is a great (free) alternative to the inbuilt merge/compare offerings in TFS/SVN etc.
Navigate to http://sourceforge.net/project/showfiles.php?group_id=58666 (get the exe at the bottom).

To set this as the default tool in VS go to Tools -> Options -> Source Control -> Visual Studio Team Foundation Server -> Configure User Tools…

Add one for compare and one for merge.

Extension: .*
Command: C:\Program Files\KDiff3\kdiff3.exe
Arguments for compare:

%1 --fname %6 %2  --fname %7
Arguments for merge:

%3 --fname %8 %2  --fname %7 %1 --fname %6 -o %4
The KDiff3 installer will automatically integrate with other popular source control systems like SVN/Tortoise and ClearCase.
UPDATE: There was a problem with the previous verison of this post the hypens in the kdiff3 arguments where coming out as single hypen and not double hypen due to some automatic formatting which WordPress performs. Thanks to Andrew W for spotting this!

CodeJAK Designs

January 3, 2008

As part of my MVC PD this week I’m creating a real website that does real things.

This website is called CodeJAK and I hope to have it go live soon.

Here is the initial design “CodeJAK design by Alex Knight” – its cool as!

So here is the low-down:

CodeJAK is a site that allows you to store code snippets – don’t let me lose you there, it’s got some cool features (okay, it *will* have some cool features).

First and foremost my plans for CodeJAK are to create a Visual Studio plugin that manages your snippets. All snippets you store in CodeJAK are stored on-line – so when you install CodeJAK on another machine and log in, all your snippets will be synched between your machines automatically.

The next feature is that you can publish your snippets if you like, i.e. share them. Then others can search for published snippets (in VS, or on the accompanying website).

Other features include community features like tagging snippets, comments on snippets, RSS feeds (subs to a feed based on user or tags or some other search query) – you get the idea (don’t steal it! – if you think its good then leave a comment and help me out!)

P.S. If you have heard of this idea before (which I havn’t) then please let me know (let me down gently).


Visual Studio 2008 RTM Available on MSDN

November 19, 2007

Just a quick note: VS 2008 RTM is available on MSDN to subscribers – http://msdn2.microsoft.com/en-gb/subscriptions/default.aspx.

Edit

ScottGu goes into some great detail about the new release, including Express and trial versions in his blog. He also gives a nice overview of some of the new features including Multi-Targeting support, built in AJAX and JavaScript intellisense, CSS support, LINQ, extension methods and lambda expressions.

Daniel Moth has a great article outlining the top 10 things to know about Visual Studio 2008 and .NET 3.5.


Follow

Get every new post delivered to your Inbox.