Monday, 18 February 2013

Windows Drivers for 0a12:0001 CSR USB Bluetooth Adapter

Recently I picked up a very cheap USB Bluetooth adapter for my laptop from ebay. It looks like this:

And here is an amazon link to the adapter: www.amazon.com/Bluetooth-USB-Micro-Adapter-Dongle

 I plugged it in and Windows 7 seemed to reconise it. The problem came when I tried to pair it with my Creative D100 speakers. The speakers were found but when trying to pair Windows said it didn't have drivers for the device. It seems that the adapter is usually supplier with a CD containing a shareware version of BlueSoleil which is a Bluetooth stack that operates independently of the Windows Bluetooth Stack. I wasn't keen on paying for this software so I could use my adapter, so managed to find a driver package for Windows for this device. 

The Asus USBBT211 uses the same chipset as this generic dongle. After installing the Asus drivers from http://www.asus.com/Networking/USBBT211_Mini_Bluetooth_Dongle#support_Download for Windows 7 x64, rebooting and trying to pair my device again it worked correctly.

Sunday, 1 April 2012

Double scrollbars in ReportViewer for IE8

Today I came across a very strange bug with reportviewer (there seem to be many) which only manifested itself in IE8.  The problem was that it created a scrollpane within a scrollpane so there were 2 sets of scrollbars.

Upon viewing the source I was able to track the problem down to the oReportDiv element which had a style attribute containing "overflow: auto;".  I could see that by removing this overflow style or setting it to "visible" the extra scroll bars would disappear.  The final solution was a challenge was the code here is contained within an iframe and I struggled with many JQuery attempts to remove the style.  Eventually I was able to remove it using the following:


    window.onload = function () {
        var viewer = document.getElementById("<%=reportViewer.ClientID %>");
        var frame = document.getElementById("ReportFrame<%=reportViewer.ClientID %>");
        if (frame != null && viewer != null) {
            var reportDiv = eval("ReportFrame<%=reportViewer.ClientID %>").document.getElementById("report").contentDocument.getElementById("oReportDiv");
            reportDiv.removeAttribute("style");
        }
    }

An event which fires in ReportViewer after the report is generated


I searched for quite a while to find a way to run a client side script whenever the ASP.Net SSRS ReportViewer control has finished rendering/generating a report.  I could not find one documented but when looking in the report viewers resulting html source I found mention of ClientController.CustomOnReportLoaded which was set to an empty function.  Using the JQuery ready function I was able to attach code to this event and have it run only after the report was generated.


$(document).ready(function () {

document.getElementById('ctl00_ctl00_DefaultContent_AdminContent_reportViewer').ClientController.CustomOnReportLoaded = function () {

        alert('You see this after Report is Generated');
        }
        });

Thursday, 15 March 2012

Inline HtmlEncode for Gridview and Repeater ASP.Net Controls

Today I had an issue where some non-standard characters needed to be displayed in a table which was created by an ASP:Repeater control.  The problem was some of these symbols were angle brackets so they were messing up the HTML of the table.

I wanted a clean and simple way to HtmlEncode these so they would render correctly.  I first tried to make the Server.HtmlEncode method work inline but I didn't have much luck.  Quite a few search results on Google said it was not possible and most people suggested encoding the text inside a DataBound event.

I eventually found the answer to doing it inline, which I think is much cleaner.  My original markup was:
<%# DataBinder.Eval(Container.DataItem, "FirstName") %>

To get this encoded I use:
<%#Server.HtmlEncode((string)DataBinder.Eval(Container.DataItem, "FirstName"))%>

I tried many variations on this but it was the cast to string that I was missing  It's not immediately obvious that cast is required as the documentation for Eval suggests a string is returned.

Wednesday, 24 November 2010

Accents clipped off text in IE7 and IE8 with Compatibility Mode

As I work in Canada, which is a bilingual country, the applications I develop usually have to be available in both English and French. Today I had a rather odd problem regarding accented characters with missing accents.

The character in question was an 'É' and I had a bug where the accent was missing. My first call was the database to check the accent was there, and it was. So I thought it was being lost due to some difference of character set between database and application layer, but breakpoints showed it was all correct at the application layer. Next I checked the source for the rendered web page and that showed the accent was there too. I even tried a copy and paste of the text and pasting the text into an editor showed the accent was present, even though it was missing in the browser.

Some more tests revealed that the accent displayed correctly in IE8 with Compatibility Mode disabled, but when Compatibility Mode was enabled the accent was clipped off. I spent some time adjusting parameters on the ASP.Net Label control and at higher levels in the mark up to get the height to increase with no more result that lots of whitespace but no accent. I was able to get the accent to appear by sacrificing the bottom few pixels of the text when setting the valign property, but this clearly wasn't acceptable. By making the text size 11 or smaller the accent appeared, but at 12 or above it was missing.

After some more searching I eventually found the CSS property to fix it. By adding "Font" tags around the label and applying "line-height: 1.1;" to the style I got it to display the accent correctly.

It seems that in the IE8 beta, Compatibility Mode was actually called IE7 Emulation Mode, a name which they really should have kept as "Compatibility" is more suggestive of standards compliance which is exactly what Compatibility Mode/IE7 Emulation Mode/IE7 is NOT.

Tuesday, 9 November 2010

Javascript popup appears again when back button pressed

One of the bugs I was looking at today was regarding use of the back button in our webapp. We have a screen that lets the user enter some data and click submit. The server side validates that data, and if necessary it alerts the user of errors using a alert issued with RegisterStartupScript.

If the user gets the error, corrects there input data, then resubmits they will be taken to the next page in the process. The problem comes when they click the back button. When the back button is pressed it takes them back to the first page which still has the startup script in it, causing the old validation error popup to appear again.

I did a lot of searching on this to see if there was a simple solution. I discovered the following:
  • There is no simple way to "unregister" a startup script.
  • Ideally the popup should be generated inside an onclick event, but this wasn't possible in my case due to the server side validation.
  • The first webpage can be set to expire, but this causes a "webpage expired" page to be displayed, which isn't any use.
  • The popup button can be pseudo disabled but that doesn't afford the user the behavior they expect.
  • Meta tags can be used to force a page to always refresh, rather than loading from the browser's cache. I wasn't able to get these to work correctly for me.
So after much effort trying different ways to do this, I went with this rather simple solution:

When we register the startup script with the alert, immediately follow the alert statement with one which will refresh the page. This ensures that the startup script is removed from the page as soon as the OK is clicked, and if the user returns to the page the pop up does not reappear.

Here's a code sample of the script injected with Page.RegisterStartupScript:

alert(\"Error with Data\");
__doPostBack('__Page', 'EmptyPostback');

Originally I was using "window.location = PageName.aspx" instead of "__doPostBack" to refresh my page without the popup, but that caused some ViewState that I needed to be lost. If you are developing in something other than ASP.Net then window.location may be better for you.

Friday, 21 May 2010

Recursive Timers Not Firing

Wasted a good while today trying to find out why some Timers I had set up kept stopping firing. Here's the scenario: I have a windows service that does 2 things.
1) Generate Alerts: Periodically generate a batch of alert emails to send to all users of a system reminding them of pending tasks they have assigned to them.
2) Send Emails: For all emails in a database table, send them.

Generate Alerts parses a cron format string to determine how often to run. Send Emails has an interval in milliseconds. One important point here is that I don't want these tasks to run every X seconds. I want them to run after X seconds and then again X seconds after the previous run has completed. Hence I don't want to use a Timer in the standard way as one execution could begin while another is still in progress.

For this reason, in each case I create a timer to do my work, and then at the end of the timer I create another timer. Note these are the Timers from System.Threading and are configured to run only once, not at every tick). Here's an example:


public void StartEmailSender(int waitTime, int retryAttempts)
{
log.Debug("Starting EmailSender");
WaitTime = new TimeSpan(0, 0, 0, 0, waitTime);
RetryAttempts = retryAttempts;

//Set the SendQueuedEmails method to run after the elapsed time.
emailSenderTimer = new Timer(delegate(object s)
{
SendQueuedEmails();
}
, null, WaitTime, new TimeSpan(-1));
log.Debug("EmailSender Started");
}

public void SendQueuedEmails()
{
log.Debug("Entering SendQueuedEmails method");

//Code to send emails goes here

//Create a new timer to run this method again after the elapsed time.
emailSenderTimer = new Timer(delegate(object s)
{
SendQueuedEmails();
}
, null, WaitTime, new TimeSpan(-1));

log.Debug("Exiting SendQueuedEmails method");
}


The original problem I was having is that the timer would run X number of times and then stop. Or one of the 2 timers would continue for longer than the other but then eventually stop. I discovered the reason was that my Timers were being Garbage Collected.

The above code is the working version. In my previous version which did not work I was not assigning the output of "new Timer(delegate(object s)" to anything. Now it gets set to a private class member. This ensures that there is always a reference to the current Timer so long as the class has not been disposed. I ensure the class is not disposed by again having a private class member in the service's main class which I initialise in the OnStart method. Hence the class is not disposed until the service is stopped and hence there is always a reference to the current Timer which is waiting to execute, and only the ones which have already completed get disposed.