I was working on a project today which involved debugging a web service, being called from separate application which we also needed to debug at the same time (So we would workout what part of the system was playing up).

The client application was already setup to call the web service on our test server. We wanted to retain this in order to replicate the production environment as closely as possible. The test server did not have visual studio installed, also, we wanted to run the web service via IIS – Not Visual Studios built in web server.

To allow us to debug from my desktop PC, I enabled remote debugging on the test server, allowing us to attach to th IIS application pool process

Step-by-Step Walk Through…

  1. From the client machine, copy folder ‘Remote Debugger’ from C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ to the server at any convenient location
  2. Run the appropriate version (X86/x64) of the listener – ‘msvsmon.exe’ on the server, found in the ‘Remote Debugger’ folder – This needs to be run as Administrator (Right click, run as administrator)
    When it runs, you should see the log, with the first line showing:
    ‘MSVMON started a new server named ‘username@servername’. Waiting for new connections’
  3. Your application will need to include PDB (Program Database) files – These include source file names, their lines and local variable names.
    See http://www.wintellect.com/CS/blogs/jrobbins/archive/2009/05/11/pdb-files-what-every-developer-must-know.aspx for a full explaination)
    If you are used to right clicking your project name and selecting publish to deploy your site/web project, be aware that this method will always compile a release build which will exclude the PDB files. Instead, you’ll need to use one of the following methods:A) ASP.Net Compilation Tool:
    See http://msdn.microsoft.com/en-us/library/ms229863.aspxfor detailsB) Build in debug mode, and manually copy/ftp the files to the server.
  4. You are now ready to commence debugging. Open Visual Studio on your client machine, select ‘Debug’ > ‘Attach to Process’. Transport should be set to ‘Default’. Enter the server name (The server you ran msvsmon.exe on) in the Qualifier box and hit enter. You will notice this will be resolved to username@servername
  5. From the list of available processes, select W3WP.EXE (IIS Worker Process) and click ‘Attach’. You will recieve a security warning – Click ‘Attach’
  6. If all has gone well, you should now be able to set a break point in your code, run the code (By opening the web site at its server/remote address) and see he break point hit.

Worth Mentioning…

  • In our scenario, we were running Windows 7 client machines connected to Windows Server 2008 Web Server
  • The code on the server needs to be the same as the code you arer using to debug – Otherwise line numbers will likely be out of sync, making debugging very difficult!
  • Debug symbols (.PDB Files) are stored in your app at: \obj\Debug

Trouble shooting…
(Only 1 suggestion right now – I’ll add to this if/when I discover others!)

  • If you cannot see W3WP.EXE in the ‘Attach to process’ dialog, ensure you have:
    • Ticked ‘Show processes from all users’
    • Ticked ‘Show processes in all sessions’
    • Ran (Browsed to) the application at least once (Or indeed, any app on the server) to load the worker process

 

If you use any of the methods in the Debug class (such as Debug.Write), you should be aware that these statements will still be in your compiled code (release or debug build) and will still run on your production server.

It could be that such statements make a negligable difference to the performance of your code, but imagine the scenario where the developer wants to check the sum or 3 or 4 items, or worse still a string concatenation to show maybe 3 or 4 variables, within a Loop – This is additional processing that is completely needless!

To avoid this, I use Pre-Processor Directives – Don’t worry about the name, like alot of development related speak they sound scary and complicated, when in fact its a very simple thing to do in order to avoid all they needless processing…

// The first line in your code, define the DEBUG symbol
#define DEBUG

// Then, where ever you use the DEBUG class, wrap your code in an if statement as follows
#if DEBUG
    DateTime startTime = DateTime.Now;
    Debug.WriteLine("ProcessRequest() Commenced: " + startTime);            
#endif

The code within the #if/#endif will be excluded from the compiled code, except of course when you are debugging.

This is a much more elegant solution than having these statements run in release code, or having to strip them all out before a release build.

The .Net TextBox control has a ‘MaxLength’ property – This of course is a handy and effective way of limiting the number of characters entered (although bear in mind this is client side only – You should back it up with a server-side check).

The ‘MaxLength’ attribute does not work with multi line text boxes (TextMode=”MultiLine”). This is because the TextBox control is then rendered as a ‘TextArea’ HTML control, which does not support the max length property.

Clearly it is important to check/limit the number of characters the user enters as this could pose a security threat, and more likely cause annoying ‘String or binary data would be truncated’ errors as the system tries in vain to squeeze 300 characters into a VarChar(200) database column.

So – What to do? Options:

a) Check server-side, if too long warn the user on a label and do carry out required action

b) Use a javascript visual count-down, coupled with a server-side check

c) Use ASP.Net regular expression validator

My personal favourite has always been option B – But project deadlines mean I don’t always have time to put this in place.

Option C is effective, secure and fast:

<asp:TextBox ID="TextBoxAddToClipboardNotes" runat="server" TextMode="MultiLine" Height="50" />
<asp:RegularExpressionValidator ID="RegExValidatorTextBoxAddToClipBoardNotes" runat="server" ControlToValidate="TextBoxAddToClipBoardNotes" ValidationExpression="^[\s\S]{0,1000}$" Text="Notes can be no more than 1000 characters" />

TheValidationExpression of ^[\s\S]{0,1000}$ means allow between 0 and 100 of any character (Lowercase – \s or Uppercase – \S). Anything else fails to match, which fires the validation control, showing a client side error – Like all ASP.Net validation controls (Apart from the custom validator – This is developer choice) This will also check serverside.

I recently had a requirement to query some data in another DataBase, which of course was not available within the main DataContext for my application. At first, I thought I would add a seperate DataContext for the related data, then query it to get the related records, generate data tables and perform a join – This all seemed rather inefficient.

After some trial and error I discovered it is possible to connect to different databases from within one single Linq2SQL data context.

Heres how I did it:
(Below assumes you already have a working Linq2SQL DataContext in place)

  1. In server explorer, add a connection to the database you want the data from (B)
  2. Open your existing DataContext (.DBML File), which will have table(s) from a different database (A)
  3. Drag the required table(s) from (B) to the DataContext
  4. For each table you use, view the properties and change the source to qualify the database name, e.g. dbo.Countries becomes DatabaseB.dbo.Countries
  5. The DataContext will only connect using one connection, so you’ll need to connect to SQL with an account that has the relevent permissions for each database

Whats the Point in this?

After doing the above, I was able to query two databases at once using a cross-database join. This in itself it nothing new – Its been possible in SQL server at least since SQL 2000, but achieving the same result in LINQ2SQL was not obvious. Its also very handy to be able to connect to another database when required – But I really would recommend considering two DataContexts for this – Although bear in mind points below…

Useful Pointers:

  • It is possible to specify the connection string when instantiating the connection – This will work fine if you only want data from one place at a time, although if this is the case you may as well have two DataConext
  • Joins will not work across DataContexts
  • I actually ended up using the same account that was used to connect to Database A, simply giving this read permission to Database B – But be very careful here!
  • It’s a good idea to rename the related classes in your DataContext so you (and future developers) know that these are from a separate database. I suggest prefixing them with the database name, followed by an underscore

Today, during unit testing, the application I’m working on threw an exception:

Cannot access a disposed object. Object name: ‘DataContext accessed after Dispose.’

This occured whilst accessing the property of a LINQ dataset returned from a method. My initial thoughts were:

“‘Whats the concern about the DataContext being disposed? I know its disposed, because thats what my code does, but my method has returned the data, now I just want to use it!”

Well, it turns out the error was due to a behaviour of LINQ commonly known as ‘Lazy Loading’. This effectivley means that related data is not automatically loaded. Kind of makes sense – After all, if we request a company or collection of company objects from our DataContext, we don’t always want to get the related Employee records, Customers etc (not to mention the orders that belong to the customers, holiday records that belong to the Employees…and so on!!)

So – Loading of related objects (records) is optional – In order to access one of them Employee records for the company you’ve retrieved, you’ll need to ask for the data in the first place – Commonly known as a ‘PreFetch’ option.

Following code would cause a ‘disposed object’ exception when we try to access Company.Employee, because the employee records will not be loaded:


using (MyDataContext MyDB = new MyDataContext(ConfigurationManager.ConnectionStrings["MyConnectionString"].ToString()))
{
company = (from c in MyDB.Company where c.ID == CompanyID select c).FirstOrDefault();
}

Here we have the same code, with Companies Employee records pre-fetched, allowing us to access Company.Employees collection


using (MyDataContext MyDB = new MyDataContext(ConfigurationManager.ConnectionStrings["MyConnectionString"].ToString()))
{
DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith<Company>(c => c.Employees);
MyDB.LoadOptions = loadOptions;
company = (from c in MyDB.Company where c.ID == CompanyID select c).FirstOrDefault();
}

If you want to pre-fetch more than one set of related data, simply add a line for each related object collection:


...
DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith<Company>(c => c.Employees);
loadOptions.LoadWith<Company>(c => c.Buildings);
loadOptions.LoadWith<Company>(c => c.Vehicles);
MyDB.LoadOptions = loadOptions;
...

Note that within Visual Studio from the LINQ2SQL Surface designer, its possible to set the ‘Delay Loaded’ property of any object property. This is false by default, meaning we always get the data for all properties when loading an object or collection of objects. I’ve not had a need to set this yet myself, but this could be hand when working with BLOB/Binary data types for storing photos for example, which you may not always be making use of.

jQuery Intellisense

March 15, 2010

As my latest project requires client-side calls to a web service, I decided to use jQuery. After numerous visits to the (Excellent) jQuery documentation It didn’t take long for me to start missing intellisense. As is often the case, a quick Google session found the answer on Scott Guthrie’s Blog - jQuery Intellisense in VS 2008

Basically its a case of:

a) Apply a patch
b) Ensure you are using the jQuery release that has the documentation included

A word of caution – You should only use the jQuery release that includes the documentation for development, remember to switch over to the standard (Ideally minified) version when you go to production. Heres why:

  • Documented Version (jquery-1.4.1-vsdoc.js): 230kb
  • Non-Documented/Standard Version (jquery-1.4.1.js): 157kb
  • Minified Version (jquery-1.4.1.min.js): 70kb

I’ve just spent nearly half a day working out why I was getting this error when running a LINQ query:

System.FormatException: String must be exactly one character long

Head on over to Stephen M Redd’s Blog for a decent explaination of why this occurs and how to fix it.

Note that this has been raised and accepted as a bug with Microsoft, so it may well be fixed by the time you read this!

Just a small tip after getting a bit caught up with this error yesterday. I know what this error means – Its a SQL error – It means your code is trying to insert a value into an indentity column, which of course should be left alone – Such a column normally auto-increments when a new line is inserted.

How did I get caught up with this one? Having checked the database table, I was lost – I had one identity column, and my LINQ query was touching this. After some thought, I sussed it – The table definition on the LINQ2SQL surface (.DBML File) was not up to date – I previously had another column set to identity, which I had later changed in the database, but not updated the related LINQ class, so when the code ran, we get the error.

Solution – Delete the table from the LINQ2SQL surface (.DBML File) and re-add it. Beware that you’ll lose any changes you might have made on your DBML, although personally I like to keep the database table and related LINQ class identical, just to save confusion.

For tidiness, when using servers controls and HMTL tags that do no contain any content, I normally close the tag within itself, e.g:

Instead of: <asp:label id=”MyLabel” runat=”server”></label>

I use: <asp:label id=”MyLabel” runat=”server”/>

This has recently tripped me up when putting a master page together – I had the title tag as <title/>, with the tag written this way, when I tried to switch from source to design mode on a WebForm attached to the master page, I received the following error:

The page has one or more <asp:Content> tags that do not correspond with <asp:ContentPlaceHolder> controls in the Master Page.

Solved simply by changing the <title/> tag to <title></title>

Just a very quick post to give you two quick, simple changes you can make to your Visual Studio config which may result in slightly less tired eyes at the end of a hard days coding:

1) Tools > Options > Environment > Fonts and Colours – Change ‘Item Background’ to Silver

2) Download and install the Consolas font back for Visual Studio installing this adds a new font to your system, which is set as a the default font in Visual Studio, at 12pt. Personally, I bump this up to 15pt!

Give it a go – You can always go back to the standard setup if you don’t like it!

Follow

Get every new post delivered to your Inbox.

Join 30 other followers