Wednesday, 8 August 2007

Reading the CrystalReportViewer report connection string from the Web.config in Crystal Reports

Again, another common requirement when working with Crystal Reports. So just where is the official documentation? ...

When using the CrystalReportViewer control it is possible to override the report's default database connection information with your own. To do this with SQL Server is well catered for, but what about us poor developers lumbered with ODBC? Perhaps we want to store and deal with connection strings from the web.config too!

Thankfully it is possible to get Crystal Reports to use a custom connection string for ODBC as this code snippet shows:

// Get document
ReportDocument doc = this.CrystalReportSource1.ReportDocument;

// Set connection string from config in existing LogonProperties
doc.DataSourceConnections[0].LogonProperties.Set("Connection String",
ConfigurationManager.AppSettings["connectionString"]);

// Add existing properties to a new collection
NameValuePairs2 logonProps = new NameValuePairs2();
logonProps.AddRange(doc.DataSourceConnections[0].LogonProperties);

// Set our new collection to be the defaults
// This causes Crystal Reports to actually use our changed properties
doc.DataSourceConnections[0].SetLogonProperties(logonProps);

How Does It Work?

The key section is the call to SetLogonProperties which causes Crystal Reports to use the new connection properties. Despite being modifiable the existing LogonProperties of a DataSourceConnection are actually read only.

Customising the CrystalReportViewer export button default filename

Crystal Reports is generally pretty useful, it's a shame some of the more common development tasks have not been exemplified by the creators. It's easy to think many things simply aren't possible, but with a bit of research you soon find most things are.

Setting the default filename used by the CrystalReportViewer web control is one of those things. The filename used defaults to the ID property of the viewer control, so to change it simply change the ID. You can do this declaratively:

<CR:CrystalReportViewer ID="MyReportName" .... />
or programattically:
this.CrystalReportViewer1.ID = "MyReportName";
Otherwise you're into manually coding export functions etc.

Saturday, 4 August 2007

ASP.Net Membership: How To Log A User In By Email Address

Great as ASP.Net 2.0 Membership and Login Controls are sometimes they fall short in functionality. A common requirement is to allow users to log-in by email address. No problem with this snippet:
void LogUserIn (string email, string password)
{
   string username = Membership.GetUserNameByEmail(email);
   if (username != null
       && Membership.ValidateUser(username, password))
   {      
       // successfully authenticated
       FormsAuthentication.RedirectFromLoginPage(username, false);
   }
   else
   {
       // Display login error
   }
}
Remember - this only makes sense if you have set the MembershipProvider's RequiresUniqueEmail property to true. Otherwise Membership.GetUserNameByEmail will simply return the first username for the email address.

Friday, 3 August 2007

Making asp:Panel DefaultButton work for a LinkButton in FireFox

The DefaultButton property of an asp:Panel is great, until you want to use a LinkButton or ImageButton. It just doesn't work in FireFox. This is because FireFox does not have a click method on it's HTML anchors. Fortunately a solution is at hand. Using this JavaScript you can add a click method to anchors that are missing one i.e. those in FireFox.
function AddClickMethod (clientId)
{   
      var anchor = document.getElementById (clientId);
      // define a click function for firefox
      if (typeof(anchor.click) == "undefined")
      {
           anchor.click = function ()
           {
               eval(this.href.replace("javascript:", ""));
           }
      }
}
You can then link the function to your default link button using:
AddClickMethod ("<%= myLinkButton.ClientID %>");
... and presto, a working asp:Panel default button!

Notes

Caveat: This does not work if you have validation controls with client script enabled. You can disable client script on a control with enableClientScript=false. I haven't tried it but I imagine it works with asp:ImageButton too.