Tim Huffam

Dotting the I and crossing the T of I.T.

  Home  |   Contact  |   Syndication    |   Login
  139 Posts | 0 Stories | 1371 Comments | 659 Trackbacks

News

Archives

Post Categories

Interesting Blogs/Links

Tuesday, July 21, 2009 #

When trying to run a .Net winforms app with a progressbar on it, I found that if it was run from a non-standard class, the marquee style did not work.

The reason was because we were running the app from our own loader class, instead of the usual winforms program.cs.  This was because we were instatiating it from VB using COM interop - I thought this was the cause of the issue - but it turns out that this is not the case... 

The problem was that our own loader class did not enable the windows XP visual styles (apparently the Marquee style is only supported on platforms later than and including Windows XP - with visual styles enabled).

So the solution (to make the Marquee style work) is to include the following line of code before instantiating your form:

Application.EnableVisualStyles();

HTH
Tim


Tuesday, July 07, 2009 #

To update the UI with values returned from an asynchronous WCF/web service call you need to make sure the coding updating the UI is running on the UI thread.  Depending on how you've performed the async remote service call, often this is done on another thread - so when the handler executes upon completion of the call it is not on the UI thread and causes a threading exception.

Within winforms, the solution is to use the Invoke() method eg the following method would be on your form or user control and could be safely called from the async service call handler:

public void UpdateCustomerName()
{
 
if (this.InvokeRequired)
  {
   
this.Invoke(new EventHandler(delegate
     
{textBox1.Text = presenter.Customer.Name;}));
  }
 
else
 
{
    textBox1.Text = presenter.Customer.Name;
  }
}

If you're using something like the MVP pattern (in winforms) then you could make your presenter base class provide some generic handling for it with these 2 members:

protected delegate void UIDeligate();/// <summary>
/// Invokes the specified method in the UI thread. This is useful for executing view methods, that update the UI, from an asynchronous callback handler in the presenter.
/// Eg: <code>OnUIThread(new Presenter&lt;ITestView&gt;.UIDeligate(View.BindCustomers));</code>
/// </summary>
///
/// <example>
/// The folling code executes the view method BindCustomrs() in the UI thread.
/// OnUIThread(new Presenter&lt;ITestView&gt;.UIDeligate(View.BindCustomers));
/// </example>
/// <param name="method">Method to invoke.</param>
protected void OnUIThread(UIDeligate method)
{
 
if (disposed) return;
 
Control control = View as Control;
 
if ((control != null) && (control.Created))
    control.Invoke(method);
 
else
   
method.DynamicInvoke();
}

These allow your presenter to handle the thread synchronization for you (as it would be the one handling the the callback processing).  In this case your UI method, in your form or usercontrol, would look like this:

public void UpdateCustomerName()
{
    textBox1.Text = presenter.Customer.Name;
}

and the presenter implementation class would call it like this:

public void customerService_CustomerUpdate(object sender, EventArgs<Customer> e)
{
  customer = e.Data;

  // Previously we would have done: 
 
// View.UpdateCustomerName();
  // but now we do this:
  OnUIThread(new Presenter<ITestView>.UIDeligate(View.BindLivingExpenseRates));
}

So now the view does not need to care about any threading/async issues.

You could also use the <methodname>Async method and <methodname>Completed event in the generated WCF client proxy - as from what I've seen the <methodname>Completed event magically executes on the UI thread (have no idea how/why).  See this article for a good example.

HTH
Tim

 


Tuesday, June 16, 2009 #

This requires a testrunconfig file that has been configured correctly.  To do this I did the following:

  1. In VS2008, right click on Solution Items folder and select Add - New Item...
  2. Select Test Run Configuration and enter the name WithCodeCoverage.testrunconfig.
  3. Open/edit this file in VS.
  4. Select the 'Code Coverage' item on the left, then selected (checked) the assemblies I wanted to instrument
  5. Click Apply to save these changes.

Note that you can select which is the active test run configuration from under the Test menu in VS2008.

Now we need to update the TFS build...

  1. Open your TFS build file (eg TFSBuild.proj)
  2. In the section starting with
    <PropertyGroup>
    <!--
    TEST ARGUMENTS...
    Add the following line (after the comments and before the closing of PropertyGroup):
    <RunConfigFile Condition=" '$(IsDesktopBuild)' != 'true' ">$(SolutionRoot)\DEV\Release1\Source\WithCodeCoverage.testrunconfig</RunConfigFile>
    (update accordingly to suit your build server paths).

That's it.  Queue a build to test - you may need to verify your server build paths to get it working (I did).

HTH
Tim


The following will make your builds (running on a TFS Server) execute your unit tests after the build:

  1. Open your build file (eg TFSBuild.proj).  VS2008 has a nice xml editor for this.
  2. Search for the RunTest node and change it from:
    <RunTest>false</RunTest>
    to:
    <RunTest>true</RunTest>
  3. Look for a section that starts with:
    <ItemGroup>
    <!--
    TEST ARGUMENTS ...
    and add nodes within this (after the comments and before the closing of the ItemGroup node) - one entry for each unit test assembly you have eg:
    <TestContainer Include="$(OutDir)\My.App.UnitTests.dll" />

Thats it - check in this file and queue a build.

An error I got while getting this working indicated that the MSTest.exe could not be found - this was because TFS Client had not been installed on the build server - once these were installed it worked fine.

Something else you may want to do is ensure that a build is triggered every time someone checks in.  To do this, edit your build definition (right click on your build within Team Explorer and choose "Edit Build Definition...") - click on the 'Trigger' item in the list on the left and make sure the "Build each check-in (more builds)" item is checked.

HTH
Tim


Friday, May 22, 2009 #

When unit testing you sometimes need to test that values are being set to the correct literal/constant value - and this value is often stored in a resources file.

However, for some reason the VS2008 'Create Private Accessor' feature did not work for me for resources (maybe be cause they're all static properties and the generated _Accessor classes need to be instantiated).  So to make these resource available within the unit test project I simply made the Resources class public (by default it's internal).

To do this:

  1. Open the resource file (eg Resources.resx) using the Visual Studio resource editor tool (just double click on the .resx file).
  2. At the top of the editor tab there is a drop down box labelled "Access Modifier" - change this from Internal to Public and save the file.
  3. Rebuild the project.

Your resources will now be accessible in your unit tests.

HTH
Tim

 


Thursday, May 14, 2009 #

This error ("Failed to access IIS metabase") can occur when you try to access your WCF when you have added for hosting within IIS.

To solve this problem do this:

  1. Reregister ASP.NET for IIS:  Open an Visual Studio Command Prompt (or a regular command prompt and cd into the .Net dir - usually: C:\WINNT\Microsoft.NET\Framework\v2.0.50727) then type:
       aspnet_regiis -i
  2. When complete, from the same command prompt run: iisreset

Verify your IIS virtual/app dir is setup correctly (uses .Net 2).  If you don't already have one...

To Host a WCF Service within IIS:

  1. Develop your service in IIS (I'm not going to tell you how to do that!) and build it.
  2. Within your computer management/MMC console (compmgmt.msc), open the Internet Information Service node and right click on the site you want to use and select New - Virtual Directory...
  3. Enter the name you want.
  4. Point this to the directory you created your WCF service project in (the project root dir - not the bin dir).
  5. Complete the wizard then back in the MMC window right click on your new virtual dir and select Properties.
  6. On the ASP.NET tab make sure uses version 2.0.50727 (or whatever your v2 is).

To test:  within the MMC console - open your new virtual dir, right click on one of your services (eg MyService.svc) and select Browse.

HTH

Tim


Tuesday, March 10, 2009 #

This post will explain how to do fading (fade out a layer) in Gimp.

Assuming you have an image open...

  1. Add a new layer
  2. Draw the part you want faded
  3. Right click on the layer in the Layers panel/window and select 'Add Layer Mask', then click on Add on the Add Layer Mask dialog (making sure the default value of 'White (full opacity)' is selected).
  4. Select the Blend/Gradient tool and set the Gradient to 'FG to GB(RGB)' .
  5. On the layer click and drag a line where you want the gradient (fade) to start and finish.  The first click is where it will be faded out and the second click is where it will start to fade.
  6. Right click on the layer in the Layers panel/window and select 'Apply Layer Mask'.

That's it.


Wednesday, February 04, 2009 #

On a fresh php installation (on WinXP using IIS 5) the mysql extension did not load.  This turned out to be because php could not find the libmysql.dll library - to resolve just put the php dir (eg "c:\xampp\php) and the ext dir (c:\xampp\php\ext) into the PATH environment variable (and restart iis).

To verify your php configuration, create a php file with the following content:
<?php
phpinfo();
?>
Save this as something like info.php into your web root dir and navigate to it with a browser eg http://localhost/info.php.

FYI - this is how I installed my own WIMP stack:

  1. Instead of doing the usual individual custom installs of these components - this time I simply downloaded the xampp and unzipped it into a dir off c: drive (c:\xampp).  This contains apache (which I won't use), mysql, php and phpmyadmin.
  2. To setup php in IIS simply add an extension mapping (mapping .php to c:\xamp\php\php5isapi.dll) - in IIS admin right click on Default Web Site  (or your other specific web site if on a windows server) and select Properties - click on Home Directory tab then click on 'Configuration...' - then click on Add and enter the details.
  3. In IIS admin create a virual directory (eg pma) pointing to the phpmyadmin dir (C:\xampp\phpmyadmin)
  4. Create an envirnment variable PHPRC and set it to your php path eg C:\xampp\php
  5. Add the php (c:\xampp\php) and ext (c:\xampp\php\ext) paths to the PATH environment variable.
  6. Run the xampp setup script: setup_xampp.bat
  7. Restart IIS (iisreset).
  8. I've also edited httpd.conf (under c:\xampp\apache\conf) to change apache to use port 81 - so I can still run apache and IIS side by side (IIS uses port 80 by default for).

That should do it. 

To test start mysql (run the mysql_start.bat script in the xampp dir) and browse to: http://localhost/pma/index.php

HTH
Tim


Sunday, February 01, 2009 #

Windows Vista Home edition has some funny quirks - and this one is a prime example...

When trying to update my hosts file I get permission denied.  That's odd - so I check the permissions and sure enough Administrator group has write access - yet I am the only administror on the system.   How's that for tricky - so I'm an admin with no admin rights - go figure.  Then I tried deleting the file then readding it....  wow - delete worked but could not re-add.

It appears the only way around this little gem is to turn off user access control (not recommended - but there seems to be no other option as the security is fairly random and not what it used to be in earlier verisons of windows).

To do this go into Control Panel, select User Accounts then choose "Turn User Account Control On or Off" and turn it off (uncheck the checkbox then click OK) - you'll need to reboot for this to take effect.

Now you can change the files.

*** Just remember to undo the security by-pass - but turning back on the user access control (same as above - checking the checkbox). ***

**** Updated: As Joe suggests below - yes the correct way would be to start your editor by using right-click - 'Run as administrator'.  However this still does not explain the bug with Vista's security model that does not allow an admin user to update the hosts file without turning off UAC.

HTH

Tim


Thursday, January 22, 2009 #

TFS has a wonderful feature whereby it marks files as changed, even though there are no changes.  These files show up in the Pending Changes window in Visual Studio (VS 2008).

To work around this,  add the following external command to your VS tools:
  1. First you need to install TFS Power Tools
  2. In VS go into Tools - External Tools and click Add
  3. Enter the following details:
    Title: Unchange
    Command: C:\Program Files\Microsoft Team Foundation Server 2008 Power Tools\tfpt.exe
    Arguments: uu /recursive /noget
    Initial Directory: $(SolutionDir)
  4. And check 'Use Output Window'
  5. Click Ok
That's it.  To test, view the Pending Changes window - usually after a 'Get Latest' is when it lists unmodified files as changed - then click Tools  - Unchange.

Thanks to Duncan Smith for this gem of info.

The fact they created a tool for this makes you wonder!

HTH
Tim

Wednesday, November 05, 2008 #

The following code shows you how you can make Silverlight controls/objects moveable by dragging them with the mouse.
Page.cs:
<UserControl x:Class="MovingObjs.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
    <Canvas x:Name="LayoutRoot" Background="White">
        <Border CornerRadius="10" x:Name="brdMovable" BorderBrush="Black" BorderThickness="2" Background="AntiqueWhite" Canvas.Top="100" Canvas.Left="10" MouseLeftButtonDown="brdMovable_MouseLeftButtonDown" MouseLeftButtonUp="brdMovable_MouseLeftButtonUp" MouseMove="brdMovable_MouseMove">
            <Grid x:Name="grid1" Width="300" Margin="5" >
                <TextBlock x:Name="txtBlkTest" Text="Test"></TextBlock>
            </Grid>
        </Border>
    </Canvas>
</UserControl>
Page.xaml.cs:
namespace MovingObjs
{
    public partial class Page : UserControl
    {
        private bool moving = false;
        private double offSetX;
        private double offSetY;
 
        public Page()
        {
            InitializeComponent();
        }
 
        private void brdMovable_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            moving = true;
            Point offset = e.GetPosition(brdMovable);
            offSetX = offset.X;
            offSetY = offset.Y;
        }
        private void brdMovable_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            moving = false;
        }
 
        private void brdMovable_MouseMove(object sender, MouseEventArgs e)
        {
            if (moving)
            {
                Canvas parent = (Canvas)this.brdMovable.Parent;
                Point p = e.GetPosition(parent);
                double x = p.X - offSetX;
                double y = p.Y - offSetY;
 
                txtBlkTest.Text = "X: " + x.ToString() + ", Y: " + y.ToString();
 
                this.brdMovable.SetValue(Canvas.LeftProperty, x);
                this.brdMovable.SetValue(Canvas.TopProperty, y);
            }
        }
    }
}
 

Wednesday, October 29, 2008 #

The following exception occurs in ASP.NET (version: 2.0.50727.1433) when you trigger an event on an ASP.Net object that has no ID set, eg clicking on a LinkButton:

System.ArgumentException: Invalid postback or callback argument.  Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page.  For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them.  If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.

The fix for this is to simply make sure the object has an ID assigned to it eg:

 

LinkButton theButton = new LinkButton();
theButton.ID = "buttonID";

Thursday, October 09, 2008 #

This will actually remove the your workspaces - unlike the VS/TFS Source Control Explorer which simply does not display them - duh!
 
From the VS command prompt:
  tf workspaces /remove:*
 

Friday, September 26, 2008 #

If a user, using Firefox 3, signs out of a web site and does not close the browser, anyone else using that browser subsequently can view the content of pages loaded by the previous user (eg in an internet cafe, or any place where workstations are shared eg universities) - exposing private/confidential data.

This only affects HTTP post requests (not gets) and only Firefox version 3 - earlier versions (1.5, 2 etc), and IE, are not affected.
 
The main points are:
  • This is definately a bug:  a violation of RFC 2616, section 14.9 that states "The Cache-Control general-header field is used to specify directives that MUST be obeyed by all caching mechanisms along the request/response chain".
  • Some companies who deem this a significant hole in their security have chosen to block requests from Firefox 3 (eg they deem it their responsibility to secure their customers private and confidential data to the best of their ability).
  • This bug has been registered with the Mozilla dev team, but currently (as of 26 Sept 2008) has a status of unconfirmed.
Related links:

Tim


Tuesday, September 09, 2008 #

The following error occured when 2 requests hit an ASP.NET (2.0) web app (using SQL Server 2005) at the same time:

The connection was not closed. The connection's current state is open

Normally this only occurs if you have a connection that is not being closed.  However in our case all connections where being closed using a try-finally block (personally I prefer using a using block).

This error only occured when the 2 request were initiated from different machines.

It turns out that the error occured because the same username was being used  for all requests (we were not interested in the username  in the app - and simply validated the request through a token and set the username to the same static string for all requests).  As soon as we made the username unique (by appending a guid to it) the error ceased to occur.

This indicates that ADO.NET uses the username as part of it's connection pooling management. 

*** UPDATE 17 Nov 08 ***
After more testing we proved this theory incorrect.  We found that the root cause of the original exception (connection state is open) was because we used a static member in one of our ORM classes - this held on to the connection, and it never got closed (hence the exception) - once we converted this to a non-static variable the problem disappeared.  However, adding the GUID to the ASP.NET username did have the above mentioned affect in several scenarios - which still leads me to believe the username has some relation/use in the connection pooling management (not sure why - as it's the process's identity that things run as - not the user's).

HTH

Tim


For some time I've been wondering if there's a better way to program business logic.  Years ago I used to write COBOL, then moved onto a 4GL, bla bla bla... and today I find myself well entrenched in OO with Microsoft's .Net.  Development times don't seem to be much better these days - and the complexity of things seems to have mushroomed. 

We went from barely-a-3GL to 4GL back to 3GL plus an explosion of things you need to consider.  We started with procedural code then moved to OO and seem to have got stuck there.  But somehow I think we need to revise our use of OO.  Business logic is predominantly procedural code - even if written in OO; it starts, follows a process, performing stuff until finished eg Customer.UpdateCreditLimit()

OO is really good for modelling things - as per the classic OO examples of a bicycle or car.  And thus they model business things quite well too - like an Invoice or a Customer. 

However, I've found that the more object oriented the code gets - the less productive, maintainable and flexible it becomes.  Not saying leave OO - far from it - it's brilliant.  It's just that we need to learn when to say 'when'.   The use of patterns has helped a huge amount - but these can also caused similar problems - when being applied where they aren't really needed - resulting in overly complex software (read: inflexible and unmaintainable and unproductive).  It's a fine line - and it's not easy to get the balance.

A major break through in this area is LINQ.  This has meant we have less clutter in our apps catering for ORM (brilliant).  This has resulted in code very similar to the old 4GL days (essentially 4GLs were just SQL based code anyway) - where all you care/code about is the business logic - caring not a jot about how or where a Customer or Order got created - and in this age of SOA - that becomes more important (as a Customer could come from many different sources - local RDBMS, company ERP, external CRM etc).  I guess you could say LINQ allows you to focus your code to be more domain specific (not saying it's a DSL).

I have been playing with workflows for donkeys of years and found that although the individual workflow systems themselves can range from very simple to incredibly complex - the individual tasks they perform need not be.   This had lead me to start thinking about applying this principle to code design at a reasonably low level....  what if we developed tasks as objects.  Each task has just one job (I've heard some people say this is how objects 'should' be coded anyway).  It has properties that can be get/set.  Keeping things dead simple, eg:

public class AdderTask
{
   
public int Addend1 { get; set
; }
   
public int Addend2 { get; set
; }
   
public int Result { get; set
; }
   
public AdderTask(int addend1, int
addend2)
    {
       
Addend1 = addend1;
       
Addend2 = addend2;
    }
   
public AdderTask
Execute()
   
{
        Result = Addend1 + Addend2;
       
return this
;
   
}
}

To run this you'd simply do this:

int result = new AdderTask(1, 2).Execute().Result;

Exposing the task's properties means you can build up get and set statements - and because the Execute method returns the task object itself you can easily use it in a single line as if it was a method on it's own - or retrieve it's property values after the Execute (these tasks would easily be adapted to work within a workflow system).

This style lends itself to expanding; rather like building blocks, you can build large workflows out of these task oriented blocks.  The workflows themselves coded just like these tasks - whereby all the business logic resides within the Execute() method.

Adding LINQ to the mix takes this to the next level - allowing you to build software that is simple to develop and understand.

I've been building a sizable system using this technique and I'm finding that I'm converting code developed using standard OO practices over to this methodology as it makes code more easily reused - but most importantly: easier to read and maintain.

In summary:

  • All input and output parameters should be implemented as properties (getter and setter accessors).
  • Provide a constructor that accepts all required parameters. A default constructor (with no parameters) is optional (I've found I never need these - but if you were to use these tasks in a workflow system they may need this).
  • Provide an Execute() method that takes no parameters and returns the object instance eg return this;
  • The object should clean up after itself. 

Other notes:

  • Originally I created a similar type of class for workflows - but I found that these ended up being no different in concept to tasks.  Likewise I've found that some tasks needed to call other tasks - so I've ended up just implementing everything as tasks.  On reflection this is actually quite valid - because, as I found when building large orchestrations using Biztalk, workflows become atomic tasks themselves when used within the context of a large orchestration (which may run many workflows and external tasks) - and the orchestration, from a highlevel could also be considered an atomic task.
  • I've found using System.Transactions.TransactionScope great for scoping transactions around many tasks when creating a macro task that runs many sub tasks.

Suggestions/comments very welcome - I'd like others to expand or comment on this.

Tim


Saturday, September 06, 2008 #

A couple of notes regarding absolute positioning in FF and IE...

Specifying position values:

  • IE allows you to omit the unit of measurement for Left and Top.  It assumes pixels eg:
        obj.style.Left = 10;
  • However FF requires that you specify the unit of measurement eg:
        obj.style.Left = "10px";

Using other elements parents to calculate your object's position:

The scenario might be you have a div that you want to position over or by another object - but that object has no position values.  In this case I use parent object values.

  • Don't use the IE specific property parentElement (this is not supported in other browsers) eg:
        obj.style.Left = otherObj.parentElement.offsetLeft + 10; 
    note in this example (that works in IE only) there is no unit of measurement.
  • Instead use the parentNode property (this works for both IE and FF) eg:
        obj.style.left = (otherObj.parentNode.offsetLeft + 10) + "px";

HTH
Tim


Wednesday, August 27, 2008 #

Sometimes Visual Studio 2008 (Team System Developer Edition - with Team Explorer and TFS Power Tools) crashes (disappearing completely) when running unit tests.

I have not yet tried SP1 for VS2008 - will hopefully try this in the next week or two.

Not really sure what causes this - but have noticed that the following error is written to the windows event log prior to the crash (not at the same time).

Event Type: Error
Event Source: VSPERF
Event Category: None
Event ID: 1406
Date:  22/08/2008
Time:  16:27:18
User:  N/A
Computer: MYPC
Description:
There was an error connecting to the Logger Engine while registering C:\Dev\DEV\Release1\Source\MyWebProject\bin\MyWebProject.dll for coverage.

Initially I thought it was a particular test or peice of target code that caused it, but found that the crash occured at seemingly random moments ie I tried running all tests and it would crash at test number 259 (out of 264), then tried running the first 100 tests and it crashed - then tried the last 20 tests and it crashed-  even tried running 1 test and it crashed.  This was the worst case of this problem - over the past few weeks it (VS crashing/disappearing) would only happen every now and then.

The only work around I've found is to replace or remove the workspace and start again...

  1. If you have pending changes, shelve them first.
  2. Using Source Control Explorer, remove the workspace.
  3. Close the solution in VS.
  4. Within a VS command prompt run the following command to remove all workspaces (if you have many workspaces and only want to remove the one workspace then specify it's name instead of the asterisk used below):
        tf workspaces /remove:*
  5. Use the Source Control Explorer to recreate a new workspace. 
    Note: if you have scripts/macros that reference your original workspace source dir, then it would pay to use the same dir - if you do,  make sure you delete the contents of this dir before reassigning it to the new workspace.

HTH
Tim


Monday, August 18, 2008 #

When trying to debug javascript using Visual Studio 2008 there a couple of things you need to do first - otherwise it (debugging) will not work and you'll get the following error when you hover over breakpoint in your javascript:

The breakpoint will not currently be hit. No symbols have been loaded for this document.

Note that this is only for debugging using IE (6) - not sure about other browsers/versions.

  1. Within IE go into Tools - Internet Options - Advanced tab and make sure the 'Disable Script Debugging' is unchecked.
  2. Make sure you have a breakpoint in your javascript.
  3. Start debugging your web app in VS.
  4. Within VS select menu item Debug - 'Attach to Process...'
  5. On the Attach to Process dialog, select the row which has explorer.exe for your app (the Title column will have you page title on it), then click Attach.

That's it - when your breakpoint is reached the VS debugger will be triggered.

HTH
Tim


Thursday, July 24, 2008 #

For those of you wanting to know just what is being sent (posted) back from the client (browser) to the server (ASP.NET) - when a postback occurs - use the following lines in your C# ASP.NET program:

 

string msg = "";
for (int
i = 0; i < Request.Form.AllKeys.Length; i++)
{
  msg += i.ToString() +
" " + Request.Form.GetKey(i) + ": " + Request.Form[Request.Form.GetKey(i)] + "\r\n"
;
}
System.Diagnostics.
Debug.WriteLine(msg);

Either look at the output window or put a break-point on the last line so you can use the debugger to view the variables values at runtime.

Note that this only the information within the HTTP POST payload.  There are also things like the HTTP headers, cookies etc (all of which you can query in a similar fashion - all within the Page.Request object).

Normally I'd use a tool like Fiddler for this type of interogation - but sometimes it's just as quick and easy to do it in the code like this.

HTH

Tim


Wednesday, July 23, 2008 #

Fresh chocolate chip cookies and fresh coffee over garden variety cookies and instant coffee

That is, while there is value in the items on the right, we value items on the left more.

The unspoken rule is that non-team members attending team meetings must come bearing the fore mentioned items


Friday, July 11, 2008 #

For those of you who don't have access to IE or FF dev toolbars - this is how we used to do client side runtime debugging...

Drop the following code into your web page (preferrably at the bottom):

<script>
function
log(text){
  document.getElementById("logArea"
).value = text;
}
function
dump(){
  log(document.body.innerHTML);
}
function logProps(obj){
 
var msg = "";
  for(var i=0;i<obj.attributes.length;i++)
  {
    msg+=obj.attributes[i].nodeName + ": " + obj.attributes[i].nodeValue + "\r\n";
  }
  log(msg);
}

</script>
<
input ondblclick="eval(this.value)" /><br
/>
<
textarea id="logArea" cols="80" rows="20"></textarea>

This should be self explanatory - the html controls provide a place to enter and run javascript (eg to query the DOM at runtime) and somewhere to dump the data.  And the javascript provides some helper functions - for dumping data and for querying all the properties of an object.

The following is a IE specific version of the for loop which may show a few other properties:
  for(x in obj)
  {
    msg+=x + ": " + obj[x] + "\r\n";
  }

HTH
Tim


Wednesday, July 09, 2008 #

For some reason some controls/tags within ASP.NET do not always get rendered/passed to the client. 

This has happened to me on a number of occasions.  It seems limited to <style> and <script> tags - but happens for both raw HTML (within the aspx designer) and dynamically created tags (eg using new HtmlGenericControl("style")...).

This is happening to controls/tags within AJAX updatepanels within, webforms and usercontrols.

Sometimes I can work around this by simply placing these controls/tags some where else within the page structure.  But the most consistent way to get around this issue is to place a non-blanking space before the tag eg:

&nbsp;<style>...

Another half-baked solution hit's the road ;-)

Update:

After some investigation, I have found a not-so-half-baked solution - for getting javascript loaded and run on a page during an AJAX postback... 

The solution is to not try and add a script tag by adding it to a control within the page - but rather use the ASP.NET AJAX ScriptManager class's RegisterStartupScript() method.  There are two overloads for this, one loads/registers the script and runs it just once (initial page load) and the other on each asynchronous postback (the latter suited my needs).

HTH
Tim


The following javascript error occurs when trying to use the Telerik controls and you haven't updated your ASP.NET (2.0) web.config file correctly.

Error: 'Telerik' is undefined

To fix make sure the following lines are within the <system.web> section of your web.config file:

<httpHandlers>
  <
add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false" />
  <
add path="ChartImage.axd" verb="*" type="Telerik.Web.UI.ChartHttpHandler, Telerik.Web.UI, Version=2008.1.515.20, Culture=neutral, PublicKeyToken=121fae78165ba3d4" validate="false" />
  <
add path="Telerik.Web.UI.WebResource.axd" verb="*" type="Telerik.Web.UI.WebResource, Telerik.Web.UI, Version=2008.1.515.20, Culture=neutral, PublicKeyToken=121fae78165ba3d4" validate="false" />
</
httpHandlers>

In my case I was missing the ScriptResource.axd line.   Also, you only need the ChartImage.axd line if you're using the chart control.

HTH
Tim


Friday, July 04, 2008 #

With a clean install of Scuttle I found that both the import bookmarks pages (importNetscape.php and import.php) do not work - instead the both display the source of the PHP files.

This is caused by both files not having the correct php declaration at the beginning of the file eg -both of these files first line was:

<?

However they should have been:

<?php

So just simply update these files.

HTH
Tim