Post date: Mar 12, 2013 1:41:32 PM
Debugging Quandis Business Objects
Troubleshooting a QBO installation requires knowledge of five key debugging tools:
browser: 'Developer Tools'
network: Fiddler
server: Visual Studio
database: SQL Server Profiler
log files: Notepad
Debugging the Browser
QBO makes use of over 40,000 lines of javascript code (prior to minification), and about 10,000 lines of css code. The good news is that only about 1/3 of all that code is 'QBO' code; the remainder is off-the-shelf stuff that rarely contributes to problems, but you still need to be able to read through it.
You are welcome to use any browser platform to debug. If you feel you wish to debug in IE, please spend 15 minutes debugging in IE 9 or earlier using their debugging tool, then spend 3 minutes debugging in Chrome, and you will reach the same conclusion that Microsoft's internal development teams reached: don't waste your time in IE. Firebug is a perfectly acceptable alternative to webkit's debugger.
Some tips from the Quandis team with respect to the webkit debugger:
webkit = the baseline open-source code of both Safari and Chrome
Find the Console, and play with it. You can experiement with what you want to make QBO 3 do before publishing js changes!
When the Console shows a js error, it include a line number on the right. Clicking that line number takes you to exactly the line of code that raised the error
Find the Sources tab: it allows you to access included js and css files
From the Sources tab, you can highlight any code, right click, and choose Evaluate in Console
Put your js in external files whenever possible; it makes troubleshooting substantially easier
Use qbo3.reload() from the console followed by a page refresh to force a refresh your js and css include files after you publish changes
Debugging the Network
QBO 3 makes extensive use of AJAX to communicate with the server. Monitoring XmlHttp requests that are transmitted over the wire is essential to effective debugging. Download Fiddler, and review the tutorials if you're not familiar with it. Some tips from the Quandis team:
Enable HTTPS debugging from Tools > Fiddler Options > HTTPS tab
Find the Inspectors tab, and peruse the various options available: Raw, WebForms, JSON, and XML inspectors are really, really useful
Composer will allow you to fake any submission to the server (including XML posts) (this is a great hacking tool - design your security assuming users will try this out!)
Statistics will allow you to measure transmission times and troubleshoot multiple simultaneous requests
Fiddler's Composer window allows you to simulate HTTP GETs and POSTs to a website. To effectively use this with QBO, do the following:
Login to a QBO site
Start Fiddler
Navigate to QBO any page
from the Inspectors > Raw tab, copy the Cookie: line from the raw request; this contains your QBO Security cookie
Click on Fiddler's Composer window
enter the URL to submit to
copy the Cookie: line from your request above to the Request Headers section
you only need the qbo.Security and ASP.NET_SessionId cookies
paste your payload into the Request Body section
click the Execute button
note a new session appears in the left pane
You can review a more robust tutorial on Fiddler's site.
Debugging the Server
All QBO developers should have a local QBO installation running under IIS on their development machine. It's fine to have this site using a connection string to a dev or uat database, but you need to have the server-side (C#) code running locally to effectively debug. If you encounter a server-side error, you need to know where to start debugging. Determine this from the stack trace found in the server-side error logs.
In the stack trace below, note the following:
Timestamp says 11:51:28 PM: this is GMT. 7 lines below that, you see 18:51:28: this is local time (EST in this case).
Scan for all of the 'Message' lines: this is the summary of errors trapped. In the stack trace below, we have:
General Exception (not so useful)
Error attempting to read the path '/Templates/Mortgage/CopyTest/CopyTest.Edit.xslt' in file object repository 'Template'. (excellent clue!)
Could not find a part of the path 'C:\inetpub\local.quandis.net\Templates\Mortgage\CopyTest\CopyTest.Edit.xslt'. (excellent clue!)
If you cannot determine the cause of the error from Message lines, scan again for a line of code that sounds like a culprit
the inner-most exception will contain the line of code that actually raised the error; if it's from System.*, it's core Microsoft code
consider reading from the bottom up in a stack trace: in this case, the very last line of the inner exception is the crux of the issue (LocalFile.Read method)
----------------------------------------
Timestamp: 3/4/2013 11:51:28 PM
Activity: 00000000-0000-0000-0000-000000000000
Message: HandlingInstanceID: ea85ac7a-9feb-4197-87ee-49549498e9b4
An exception of type 'qbo.Exception.GeneralException' occurred and was caught.
------------------------------------------------------------------------------
03/04/2013 18:51:28
Type : qbo.Exception.GeneralException, qbo.Exception, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Message : General Exception
Source :
Help link :
Manager : Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ExceptionManagerImpl
Data : System.Collections.ListDictionaryInternal
TargetSite :
HResult : -2146233088
ThrowException : True
Stack Trace : The stack trace is unavailable.
Additional Info:
MachineName : MINBAR
TimeStamp : 3/4/2013 11:51:28 PM
FullName : Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=5.0.414.0, Culture=neutral, PublicKeyToken=null
AppDomainName : /LM/W3SVC/1/ROOT-1-130069145369323941
ThreadIdentity : admin@quandis.com
WindowsIdentity : IIS APPPOOL\DefaultAppPool
Inner Exception
---------------
Type : qbo.Exception.GeneralException, qbo.Exception, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Message : Error attempting to read the path '/Templates/Mortgage/CopyTest/CopyTest.Edit.xslt' in file object repository 'Template'.
Source : qbo.Attachment
Help link :
Manager : Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ExceptionManagerImpl
Data : System.Collections.ListDictionaryInternal
TargetSite : qbo.Attachment.AttachmentInfo Read(System.IO.Stream, System.String)
HResult : -2146233088
ThrowException : True
Stack Trace : at qbo.Attachment.FileObjects.LocalFile.Read(Stream stream, String relativePath) in C:\Source\Trunk\qbo.3\qbo.Core\Application Tier\qbo.Attachment\FileObjects\LocalFile.cs:line 60
at qbo.Attachment.AttachmentObject.Read(Stream streamToWriteTo) in C:\Source\Trunk\qbo.3\qbo.Core\Application Tier\qbo.Attachment\Attachment.cs:line 435
at qbo.Attachment.AttachmentObject.ReadMemory() in C:\Source\Trunk\qbo.3\qbo.Core\Application Tier\qbo.Attachment\Attachment.cs:line 446
at qbo.Attachment.AttachmentObject.ReadXsl(XsltSettings settings) in C:\Source\Trunk\qbo.3\qbo.Core\Application Tier\qbo.Attachment\Attachment.cs:line 511
at qbo.Attachment.AttachmentObject.ReadXsl() in C:\Source\Trunk\qbo.3\qbo.Core\Application Tier\qbo.Attachment\Attachment.cs:line 500
at qbo.Decision.ImportFormTemplateObject.get_EditTransform() in C:\Source\Trunk\qbo.3\qbo.Core\Application Tier\qbo.Decision\ImportFormTemplate.cs:line 248
at qbo.DecisionWeb.ImportForm.RenderEdit(HttpContext context) in C:\Source\Trunk\qbo.3\qbo.Core\Web Tier\qbo.DecisionWeb\Decision\ImportForm.ashx.cs:line 152
at qbo.DecisionWeb.ImportForm.ProcessRequest(HttpContext context) in C:\Source\Trunk\qbo.3\qbo.Core\Web Tier\qbo.DecisionWeb\Decision\ImportForm.ashx.cs:line 60
Inner Exception
---------------
Type : System.IO.DirectoryNotFoundException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Message : Could not find a part of the path 'C:\inetpub\local.quandis.net\Templates\Mortgage\CopyTest\CopyTest.Edit.xslt'.
Source : mscorlib
Help link :
Data : System.Collections.ListDictionaryInternal
TargetSite : Void WinIOError(Int32, System.String)
HResult : -2147024893
Stack Trace : at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access)
at qbo.Attachment.FileObjects.LocalFile.Read(Stream stream, String relativePath) in C:\Source\Trunk\qbo.3\qbo.Core\Application Tier\qbo.Attachment\FileObjects\LocalFile.cs:line 39
Category: General
Priority: 0
EventId: 100
Severity: Error
Title:Enterprise Library Exception Handling
Machine: MINBAR
App Domain: /LM/W3SVC/1/ROOT-1-130069145369323941
ProcessId: 5584
Process Name: c:\windows\system32\inetsrv\w3wp.exe
Thread Name:
Win32 ThreadId:7172
Extended Properties:
----------------------------------------
Debugging the Database
Debugging the database should be used when other technique fail. Profiling a server, particularly a PROD server, is 'expensive' in that the act of profiling can degrade the performance of the db all by itself. Thus, you should coordinate with a DBA or QBO architect if you need to profile a database for your debugging efforts. When profiling QBO3, consider:
Use the 'TSQL' template
Under 'Events Selection':
enable RPC:Starting and SQL:BatchStarting (and/or their Ending counterparts)
disable all Security Audit and Sessions checkboxes
check on Show all columns
click on Column Filters and add a filter on the DatabaseName for the database you are troubleshooting
Pause the trace until you are ready to replicate the issue
Run the trace, replicate the issue, and re-pause the trace
Log Files
All QBO errors are logged to the web server. QBO 3 logging uses the Microsoft Enterprise Library Logging sinks, including a rolling log file that is renamed each day. Some tips include:
If both IIS and the Queue Processor are running, they may conflict in their attempts to write to the rolling.log file. If so, you may see a {Guid}rolling.log file on the web server. Look at it's contents if you don't see what you expect in the standard rolling.log.