Web 2.0 ASP.NET

A Blog about ASP.NET, MVC, Web 2.0, AJAX, SQL server and other web technologies.
Helping the little guy win!

Top ASP.NET Developments Tools

ASP.NET Toolkit
I always get asked what my favourite development tools are, so in my last article I talked about my favourite Visual Studio add-ins. This time I want to talk about my favourite ASP.NET Development Tools.

Telerik Rad Controls for ASP.NET Ajax http://www.telerik.com/
This is a paid for set of controls which really sets the bar in the control suite market. It is not cheap, but if you are intending to build multiple applications then the return on investment is huge. The RadEditor, for example, literally does ninety percent of the work for you in terms of building a seriously functioned CMS. If you want to get a handle on what the controls can do check out the Telerik Site. I really love the AJAX scheduler control, I recently manage to hook it up to a Google calendar feed! The latest versions of the Rad Controls Suites Q1 2010 are now available for trial download here: http://www.telerik.com/products/aspnet-ajax.aspx

Jetbrains dotTrace Memory Profiler http://www.jetbrains.com/profiler/
This is a life saver when you are trying to find memory leaks and potential bottlenecks in your application, if like me have spent hours going through old code, then this is truly an essential tool. I also use it to sandbox new ideas for code and it has an estimation feature which immediately shows you the potential performance gains you can get by removing a bottleneck. [EDIT] since writing this I have been able to obtain some dotTrace discount coupons and extended 60 day trials from Jetbrains, see here for details: http://web2asp.net/2010/03/dot-trace-discount-coupon.html[/EDIT]

UrlRewriting.net http://www.urlrewriting.net/149/en/home.html
This great little free dll enables you to rewrite dynamic URL’s to SEO friendly versions in your ASP.NET applications and was written by Albert Weinert & Thomas Bandt back in 2006, essentially you use Regexes in your web.config file to set it up. This has saved my life on many occasions when developing applications which get hosted on shared web hosting. So a big thank you to Albert & Thomas (who used to personally answer support requests) great job boys!

Fiddler 2 http://www.fiddlertool.com/fiddler/
This is a Http debug proxy which can be accessed either from internet explorer or directly. If you want take a hard look at response and request information and even get statistics on the performance of your pages, this is IMHO the best tool for the job and it is free. At a more advanced level you can extend it’s functionality using rules (programmed in a any .NET language) and you can set up custom requests to test the response from your applications. I use it sometimes on my ASP.NET mobile web form apps to send mobile user-agents with requests to see what is returned.

Internet Explorer Developer Toolbar http://www.microsoft.com/downloads/details.aspx?FamilyID=e59c3964-672d-4511-bb3e-2d5e1db91038&DisplayLang=en
This tool is an Internet Explorer Add-in, much like firebug for Firefox ,which lets you mess around with the document model, locate html items in a page and bunch of other useful gadgets. My personal favourite is that You can set up custom window sizes so that you can preview your sites at various resolutions. I also use it to tweak CSS in my designs without committing the changes to the CSS file.

Regex Workbench http://code.msdn.microsoft.com/RegexWorkbench/Release/ProjectReleases.aspx?ReleaseId=406
The Regex Workbench is a cool (free) sandbox for writing regular expressions. For the rusty amongst you, it also includes a library of insertable regex codes for captures, forward lookups and character identifiers. You can run your Regexes on any text or html that you can think of by dropping it into the textbox and apply different Regex parameters (single line, multi line etc) to see the results. Once you have honed your creation, there is a simple export function which generates the proper code for C# and VB.NET, so you don’t need to worry about escaping your Regex correctly, just paste it into your app code. Thank you Eric Gu, nice job feller!

RSS Toolkit http://www.codeplex.com/ASPNETRSSToolkit
I recently blogged about these tools in detail here: http://web2asp.net/2009/01/using-aspnet-rss-toolkit-to-quickly.html
If you are looking to either syndicate or consume RSS content, don’t reinvent the wheel! It does the job and it’s free, nuff said!

Conclusion
Hope you find these useful, there are of course many other dev tools around, these are just a few of my personal favourites. In another post I will talk about some of the tools I use for developing Mobile ASP.NET sites.

kick it on DotNetKicks.com   Shout it

Top Visual Studio Add-ins

[Edited 21st April 2010]

Visual Studio Add-ins in my Development Toolkit

I am often asked what my favourite development tools are, so I thought I’d write down a few that I use and why. I have split this list in 2 as some of these are Visual Studio Add-ins and others are just standalone applications here are the Visual Studio Add-ins. Each Visual Studio Add-in is also compatible with Visual Studio 2010.

Visual Studio Add-in List

1. Jetbrains Resharper 5 http://www.jetbrains.com/resharper/index.html
This Visual Studio add-in does not work with Visual Studio Express editions so if you don’t have VS standard or above, then move to the next one. If you do however, this really is one of the best productivity enhancing tools out there. At its simplest the intellisense enhancements alone are worth the money and in my book are far superior to the out of the box VS version. Add to that the visual highlighting of problematic code, recommendations for best practices coding and cross solution code cleanup and you have a formidable tool for ensuring the quality of your code and speeding up the development process. You can also take it to the next level and create your own surround with templates and keyboard shortcuts. Resharper also rocks when you want to to run NUnit tests, it ads a bunch of context commands for Unit testing and runs a modal window so that you can visually se the tests running (and hopefully passing!) in fact I would be lost without it  Visual Studio 2010 will be released in just a few days and Resharper 5 will also be released at the same time, Resharper 5 gives much more ASP.NET support, including a Html viewing window which makes it ultra easy to navigate through complex pages, also there is additional MVC support, my experience with the RC is that it is faster than ever and I really like the enhanced Intellisense for ASP.NET and cutting edge Unit testing integration. You can download a 30 day Trial of ReSharper 5 here:
Resharper 5 30 Day Trial

2. Ghost doc http://submain.com/products/ghostdoc.aspx
This add-in takes the pain out of generating documentation by allowing you to quickly add comments to your methods and properties. It is customizable so you can set up the way you want the comments to appear and there are versions for VS2003,2005,2008 and 2010. It is free as well so big ups to Roland Weigelt for this great tool.

3. Power Commands for VS2008 http://code.msdn.microsoft.com/PowerCommands
With functions like 'format and order using on save' and 'format document on save' this free add-in is an easy choice and easy win. My personal favourites are ‘email code snippet’ which means you can highlight a section of code, right click and have an outlook mail window open with the code already in it and the 'collapse all projects' command which collapses all the projects in your solution pane. This add-in is also free.

4. Visual NDepend http://www.ndepend.com/
You ever have that feeling where you're not sure if you're awake or still dreaming? If you will excuse the matrix reference, this excellent Visual Studio Add-in developed by Patrick Smacchia Microsoft MVP, answers many questions that I find myself asking or being asked at dev meetings. How good is my code? NDepend visually shows you exactly where your weak links are and for Lead Developers and CTO’s offers metrics and a ultra cool querying interface. NDepend is also invaluable if you want to plan a major refactor or to assert design rules. At it’s most basic you get a pat on the back and the feeling that you have written some decent code (or not as the case may be!), but the more you dig into it and see how deep the rabbit hole goes (apologies for another blatant Morpheus quote!) the more valuable it becomes. This is a big picture tool specifically designed to make the big picture easy to understand.


Next time I will list the other standalone dev tools I use regularly.
kick it on DotNetKicks.com

Why MVC?

Why MVC?
Yet another MVC introduction? Not exactly… I bet you are all sick and tired of hearing the acronym MVC these days and if you are here to grab a 4 dummies guide to set you on your merry way then Response.Redirect immediately as this is more about the ‘why’ than the code.

Like all big Microsoft innovations there have been much fanfares, Alphas and more recently a Beta with a go live license to wet appetites and fuel the blogsphere with new content, but what is it about MVC which is making headlines and more importantly, why would you (the developer) want to give this a shot?

Control Freaks
I am sick and tired of hearing people complain about the bloated html and unnecessary code which ASP.NET emits to the browser by default, but let’s be frank (or Dave or whoever you want to be) most of these people have been developing apps the drag and drop (MS Tutorial cool aid method) way without really understanding what is going on under the ASP.NET skirt. So again if you happy GUI’ing your way to the programming hall of fame (and I am not at all saying that is impossible) then you can also Response.Redirect.

MVC is pretty much aimed at developers who do understand the rudimentary function of POST and GET and who really want ultimate control over what HTML is rendered to the browser. This ability is already in ASP.NET but MVC takes this a step further entirely removing page bloat like viewstate and the ever lengthening control id’s rendered by ASP.NET currently. It also supports serious unit testing which has, up to now, been very difficult to accomplish in ASP.NET applications. Other real world bonuses include having control over the url’s which render content, which should appeal to the SEO literate amongst you. JQuery is also built in so you have no excuse for not tinkering with (IMHO) the best JavaScript library out there.

Update an existing application?
Good luck to you! MVC does not support the current arsenal of ASP.NET web controls so any Lead Dev who has yet to read the brochure, will need to think very seriously before committing to MVC. Most of the introductions I have seen state this is probably more suited to green field projects, but I wouldn’t rule it out completely. The bandwidth money saved, enhanced SEO and potentially huge performance improvements could far outweigh the cost of development, not to mention the benefits of a properly unit tested code and transparency of function gained by using the Model View Controller model.

Man Up!
So if you are sick and tired of being branded a code pussy by the greasy Ruby and PHP cowboys and you want to take control and responsibility for what your app dishes out to the client then get your stirrups on, mount that pony and get on the MVC trail….
kick it on DotNetKicks.com

Using GZip or Deflate in ASP.NET to improve application performance and conserve bandwith

Introduction
One of the big complaints about ASP.NET, by proponents of clean semantic mark up, is that the raw html emitted by the ASP.NET engine can be bloated and can, as a result, degrade performance. Of course we could go through all our applications and recode our controls to output cleaner mark up, obviously this takes a lot of time and likely not the choice made by most lead developers when choosing new projects to work on. This article describes a quick method to decrease the size of code sent to browsers and speed up the loading process for users.

GZip/Deflate
GZip and Deflate are compressions used to send data over Http, the majority of browsers now support the decompression of these formats and so they are the best choice for us to use. Developers with direct access to the administration of IIS could of course enable Http Compression (see Here for instructions for setting up IIS). But, if you are using shared hosting or this kind of administration is not feasible, we can use the System.IO.Compression assembly to perform the compression at the application level.

How
Basically, we add a bit of code to our page load which compresses the output stream of the Response. I tend to put this code in my custom page class in the app_code folder so that it runs automatically for each page, but that may not be suitable for your situation so I will leave this choice up to you.

Obviously, we can’t ignore the fact that some browsers don’t like compressed content, so the first thing we do is to check the Request Headers for the accept encoding header for GZip (most of the major browsers accept both, I have favoured GZip in this snippet as it seems the more popular of the two, but again the choice is yours). Once the allowed compression type is determined the code modifies the Response Filter with the appropriate Stream Compression.


if (Request.Headers["Accept-encoding"] != null && Request.Headers["Accept-encoding"].Contains("gzip"))
{
Response.Filter = new GZipStream(Response.Filter, CompressionMode.Compress, true);
Response.AppendHeader("Content-encoding", "gzip");
}
else if (Request.Headers["Accept-encoding"] != null && Request.Headers["Accept-encoding"].Contains("deflate"))
{
Response.Filter = new DeflateStream(Response.Filter, CompressionMode.Compress, true);
Response.AppendHeader("Content-encoding", "deflate");
}


And thats it! When applied, I saw a noticeable speed up in the page load and on closer inspection in fiddler the size of the documents downloaded had decreased from 16-17Kb to 6Kb in many cases. This is a significant improvement if bandwidth is an issue for you and you can really see how this could make a huge difference to your bandwidth costs and to the performance of your applications.

kick it on DotNetKicks.com

Google Hosts JQuery, Scriptaculous, Prototype and Even the Yahoo User Interface Library

Introduction
For the AJAXians and Web 2.0 citizens amongst you, the wonderful peeps at the Googleplex have done it yet again. Those of you familiar with the concept of NOT reinventing the JavaScript wheel should already be (if not should be) reaping the benefits of the great JavaScript libraries out there. My personal weapon of choice is JQuery (for which you can even get intellisense for in VS2008 these days, check out Scott Gu's blog even if you are not interested in JQuery intellisense, it’s probably the best ASP.NET blog out there).

Anyway, I digress, one of the problems with these libraries is that they often change frequently and while we all try to keep on top of the changes and new builds even the best of us can miss one. Not only that, having to host the libraries in your projects and then changing code to support a new release can mean that users may still have cached versions of the old JavaScript files stuck in their temporary internet files causing JavaScript errors and in the worst case rendering your AJAX masterpieces unusable.

Enter the Google AJAX Library API
The guys at Google have reached out to the major stakeholders in these libraries and are now hosting the different builds of the Libraries for direct loading from google servers. They have committed to maintaining the older versions of these libraries too so there is no chance you can find yourself a couple of JavaScript files less than an application (nice nerdy euphemism there). The cache headers are also set correctly, so this means that you will not have any cached JavaScript issues either.

Setting it all up
Setting it up couldn’t be simpler:


<script src="http://www.google.com/jsapi"></script>
<script>
// Load jQuery
google.load("jquery", "1");
</script>


Yes that really is it! For the performance connoisseurs out there, you can choose to add this at the end of your page so the scripts load last (provided nothing is required in the page load).

Plus you can add as many libraries as you like using google.Load (go for it load the whole lot!)


<script src="http://www.google.com/jsapi"></script>
<script>
google.load("jquery", "1.3.0");
google.load("jqueryui", "1.5.3");
google.load("prototype", "1.6.0.3");
google.load("scriptaculous", "1.8.2");
google.load("mootools", "1.2.1");
google.load("dojo", "1.2.3");
google.load("swfobject", "2.1");
google.load("yui", "2.6.0");
</script>


For more information see the complete API documentation at google:

Google AJAX Libraries API

Happy scripting!

kick it on DotNetKicks.com

Master Pages The n Commandments

Introduction
Used properly the ASP.NET Master Page can be a useful and time saving mechanism, but there are some pitfalls which developers should be aware of and some common architectural mistakes which can render them more trouble than they are worth. Hopefully by reading this you can avoid some of the common (cough?*$ mistakes I already made) problems.

The n Commandments
The first mistake I made when using master pages was to look at them as a magic answer to the custom inherited page class many of us used in ASP.NET 1.1, when in actual fact the master page is essentially a solution to a work around that was commonly used back then i.e. stacking up user controls on a page to handle header, content and footer sections. The custom page class is still very much required and while you can get a Master Page to function like it, the heartache involved is simply not worth it. Simply put, the Master Page only acts like a Master when the page is initializing, after that it is essentially a user control and in this we find the cause of most problems. Trust me, keep your custom page class in your app_code directory where it should be and think of the MasterPage as a convenient way to uniformly style sites and to include other site wide tags like CSS and Javascript references.

The second mistake I made was trying to access Master Page properties from my user controls, while this can be done, it involves referencing the virtual path in the .ascx file then casting Page.Master to the referenced MasterPage.


.ascx
<%@ Reference VirtualPath="~/MyMasterPage.master" %>
.cs
MyMasterPage m = (MyMasterMaster) Page.Master;


The problem with this is, say for example you start adding a javascript reference from within your user control and then you realize you need to add a different javascript reference from within the page hosting the user control, then adding another reference to the master page in the host page will cause a circular reference. Simply put, it makes much more sense to make the master page clever enough to know what Javascript or CSS references to add. Things like the title tags can be accessed directly



Page.Title


Another easy mistake is in architectures which involve using multiple user controls on the page, which are shown or hidden depending on the function of that page. While this one is not necessarily isolated to master pages it is important in the context of web 2.0 desktop like web applications which magically have elements appear and disappear. Just because an element is not visible it does not at all mean that the code will not run, I worked on an application recently in which I managed to literally quadruple the speed in a matter of minutes by making sure the code in invisible user controls wasn’t running until actually required. The previous developer had presumed that code only runs if the control is visible (logical), the choice of logically breaking up functions into specific user controls was spot on however, this oversight caused the app to run like a snail on ketamine.

Conclusion
Hopefully these pointers will help you have a painless Master Page experience!

kick it on DotNetKicks.com

Using The ASP.NET RSS Toolkit to quickly include syndicated content in your own site

Introduction
This being the age of the mash up, those of you who have yet to hear about RSS have been living under a rock! RSS (Really Simple Syndication) is the syndication weapon of choice for most blogs and feeds.

For those of you who are delving into the possibilities of utilising syndicated content in ASP.NET, the ASP.NET RSS Toolkit is a very powerful yet simple tool which will help you quickly integrate content syndicated from other sites.

Why the RSS Toolkit?
Simply put, why reinvent the wheel? I am not one to look a gift horse in the mouth, so when I am presented with a solution which works, you won’t find me asking too many questions. Not so simply put, there are a bunch of solutions out there which do the same job, but, in my humble opinion not quite as well rounded as the RSS Toolkit. At a basic level it provides a very simple interface to provide RSS content to databound controls, not only that but you can also automatically create strongly typed objects for different feeds by using it’s very clever command line utility.

Possible Problems
As always, nothing is perfect and the RSS Toolkit currently doesn’t handle RSS feeds which use the Dublin Core meta data specification, but as most of the big blogs and feeds don’t use it for my book this is a small price to pay. Other problems I often read people moaning about are applications which break when the feed is unavailable. This, my friends, is self inflicted and actually bad programming. Rule one is checking that resources exist before trying to use them and of course putting try catch blocks around code which may potentially break under some circumstances, in this case an RSS feed being unavailable, should go without saying (I said it anyway) just to be sure.

Shut up and give me the code!
Not mine to give, but you can snag a copy over at codeplex:
http://www.codeplex.com/ASPNETRSSToolkit

Example

Here we simply create an RSS data source for a databound control (in this case a DataGrid).


using RssToolkit.Rss;
using RssToolkit.Web.WebControls;

public partial class FeedTest : System.Web.Page
{
protected void Page_Load(object sender, EventArgs e)
{
RssDataSource rds = new RssDataSource();
rds.Url = “your choice of feed url goes here”
dgRSS.DataSource = rds;
dgRSS.DataBind();
}
}



kick it on DotNetKicks.com

Mobile ASP.NET Development: Indentifying the main Japanese carriers (DoCoMo, Softbank, AU KDDI, JPhone, Vodafone)

Introduction
Those of you who have delved into developing mobile sites with ASP.NET mobile controls, may have come up against a lack of real world examples in the documentation. The benefits of dynamic rendering and device specific rendering look great on paper, but as I have found, while it works a lot of the time there are some limitations. In Japan there are several main carriers who each offer different browsers and capabilities, while this article doesn’t dig deeply into these as there are plenty of online resources and each of the carriers have their own development portals where you can easily find the information you may need. This article describes a way of identifying the main Japanese carriers so that you can handle the user experience accordingly.

Method

So how do you do that then? well simply put, each of these carriers browsers have distinct user agents, so we are going create a custom capabilities class to parse the user agent string. To make this work we also need to add a deviceFilters section to our web.config file and lastly we are going to use a DeviceSpecific control in our mobile ASPX page to dynamically render content on a per carrier basis.

Mobile ASPX
The string you use for the choice filter must match the name of the device filter in your web.config it is case specific so be careful. Also note that I have surrounded the deviceSpecific control with a panel, this then enables me to find the control in ContentTemplate that I want to manipulate:


Literal litLink = (Literal)pnCarrier.Content.FindControl("litLink");



<mobile:Panel ID="pnlCarrier" runat="server">
<DeviceSpecific ID="dsCarrier" runat="server">
<Choice Filter="isDocomo">
<ContentTemplate>
<asp:literal id="litLink" runat="server" /><mobile:TextView ID="tvBreak" Runat="server"><br></mobile:TextView>
</ContentTemplate>
</Choice>
<Choice Filter="isSoftbank">
<ContentTemplate>
<asp:literal id="litLink" runat="server" /><mobile:TextView ID="tvBreak" Runat="server"><br></mobile:TextView>
</ContentTemplate>
</Choice>
<Choice Filter="isAuKddi">
<ContentTemplate>
<asp:literal id="litLink" runat="server" /><mobile:TextView ID="tvBreak" Runat="server"><br></mobile:TextView>
</ContentTemplate>
</Choice>
<Choice Filter="isJPhone">
<ContentTemplate>
<asp:literal id="litLink" runat="server" /><mobile:TextView ID="tvBreak" Runat="server"><br></mobile:TextView>
</ContentTemplate>
</Choice>
</DeviceSpecific>
</mobile:Panel>



Code Behind
This code evaluates the selected choice in the device specific control and renders a string accordingly, obviously you would do some more exciting stuff once you have determined the carrier, I used a literal to assign a string for example purposes.



if (dsCarrier.SelectedChoice == null) return;

Literal litLink = (Literal)pnCarrier.Content.FindControl("litLink");
switch (dsCarrier.SelectedChoice.Filter)
{
case MobileFilterNames.isDocomo:
litLink.Text = "DoCoMo";
break;
case MobileFilterNames.isAuKddi:
litLink.Text = "AU KDDI";
break;
case MobileFilterNames.isSoftbank:
litLink.Text = "SoftBank";
break;
case MobileFilterNames.isJPhone:
litLink.Text = "J-Phone";
break;
}



Custom Capabilities Class Code

Each of the methods which evaluate the carrier take the parameters MobileCapabilities and a string argument, they are also public and static and return boolean values.


using System.Web;
using System.Web.Mobile;

namespace Dlr
{
public class MobileCapabilityEvaluators
{
#region MemberVariables

private readonly static string[] SoftBankUserAgentList = new string[]
{
"Vodafone",
"SoftBank",
};

private readonly static string[] JphoneUserAgentList = new string[]
{
"J-PHONE",
};

private readonly static string[] AuKddiUserAgentList = new string[]
{
"KDDI",
};

private readonly static string[] DocomoUserAgentList = new string[]
{
"DOCOMO/2.0",
};

private readonly static string[] RegularUserAgentList = new string[]
{
"Mozilla/4.0",
"Mozilla/5.0",
};

#endregion

#region isSoftBank

/// <summary>
/// Determines whether [is soft bank] [the specified capabilities].
/// </summary>
/// <param name="capabilities">The capabilities.</param>
/// <param name="argument">The argument.</param>
/// <returns>
/// <c>true</c> if [is soft bank] [the specified capabilities]; otherwise, <c>false</c>.
/// </returns>
public static bool IsSoftbank(MobileCapabilities capabilities, string argument)
{
if (HttpContext.Current.Request.UserAgent != null)
{
string[] agentInfo = HttpContext.Current.Request.UserAgent.Split('/');
if (agentInfo.Length == 0)
return false;
foreach (string agent in SoftBankUserAgentList)
if (agentInfo[0].ToLower().Contains(agent.ToLower()))
return true;
}
return false;
}

#endregion

#region isJPhone

/// <summary>
/// Determines whether [is soft bank] [the specified capabilities].
/// </summary>
/// <param name="capabilities">The capabilities.</param>
/// <param name="argument">The argument.</param>
/// <returns>
/// <c>true</c> if [is soft bank] [the specified capabilities]; otherwise, <c>false</c>.
/// </returns>
public static bool IsJPhone(MobileCapabilities capabilities, string argument)
{
if (HttpContext.Current.Request.UserAgent != null)
{
string[] agentInfo = HttpContext.Current.Request.UserAgent.Split('/');
if (agentInfo.Length == 0)
return false;
foreach (string agent in JphoneUserAgentList)
if (agentInfo[0].ToLower().Contains(agent.ToLower()))
return true;
}
return false;
}

#endregion

#region isAuKddi

/// <summary>
/// Determines whether [is au kddi] [the specified capabilities].
/// </summary>
/// <param name="capabilities">The capabilities.</param>
/// <param name="argument">The argument.</param>
/// <returns>
/// <c>true</c> if [is au kddi] [the specified capabilities]; otherwise, <c>false</c>.
/// </returns>
public static bool IsAuKddi(MobileCapabilities capabilities, string argument)
{
if (HttpContext.Current.Request.UserAgent != null)
{
string[] agentInfo = HttpContext.Current.Request.UserAgent.Split('/');
if (agentInfo.Length == 0)
return false;
foreach (string agent in AuKddiUserAgentList)
if (agentInfo[0].ToLower().Contains(agent.ToLower()))
return true;
}
return false;
}

#endregion

#region isDocomo

/// <summary>
/// Determines whether [is docomo] [the specified capabilities].
/// </summary>
/// <param name="capabilities">The capabilities.</param>
/// <param name="argument">The argument.</param>
/// <returns>
/// <c>true</c> if [is docomo] [the specified capabilities]; otherwise, <c>false</c>.
/// </returns>
public static bool IsDocomo(MobileCapabilities capabilities, string argument)
{
if (HttpContext.Current.Request.UserAgent != null)
{
string userAgent = HttpContext.Current.Request.UserAgent;
if (userAgent.Length == 0)
return false;
foreach (string agent in DocomoUserAgentList)
if (userAgent.ToLower().Contains(agent.ToLower()))
return true;
}
return false;
}

#endregion

#region isRegular

/// <summary>
/// Determines whether [is regular] [the specified capabilities].
/// </summary>
/// <param name="capabilities">The capabilities.</param>
/// <param name="argument">The argument.</param>
/// <returns>
/// <c>true</c> if [is regular] [the specified capabilities]; otherwise, <c>false</c>.
/// </returns>
public static bool IsRegular(MobileCapabilities capabilities, string argument)
{
if (HttpContext.Current.Request.UserAgent != null)
{
string userAgent = HttpContext.Current.Request.UserAgent;
if (userAgent.Length == 0)
return false;
foreach (string agent in RegularUserAgentList)
if (userAgent.ToLower().Contains(agent.ToLower()))
return true;
}
return false;
}

#endregion
}
}


web.config
Notice each filter has a unique name, points to the class and assembly and lastly indicates the method in the class used to determine whether the filter returns true.


<deviceFilters>
<filter name="isDocomo" type="Dlr.MobileCapabilityEvaluators,Dlr " method="IsDocomo"/>
<filter name="isSoftbank" type="Dlr.MobileCapabilityEvaluators,Dlr " method="IsSoftbank"/>
<filter name="isAuKddi" type="Dlr.MobileCapabilityEvaluators,Dlr " method="IsAuKddi"/>
<filter name="isRegular" type="Dlr.MobileCapabilityEvaluators,Dlr " method="IsRegular"/>
<filter name="isJPhone" type="Dlr. MobileCapabilityEvaluators,Dlr " method="IsJPhone"/>
</deviceFilters>

kick it on DotNetKicks.com

Tracking visitors in ASP.NET by using an image and AJAX PageMethods

Introduction
I often see developers asking for ways to track page usage so I thought I’d share a trick I often use, it’s very simple, doesn’t require Http Handlers and takes just a couple of minutes to implement.

The Method
Ok, so let’s get to it as it will take you less time to implement than it takes me to tell you! Every image has an onload event associated with it, so using this event we are going to call a page method in our code behind file *blink* yes that simple! Slapping yourself already, yes I did too when it came to me.

1. Add a script manager to your page or master page (tut tut if don’t have one already, this is the AJAX revolution!) Make sure you set the EnablePageMethods property to true). Also make sure the script manager is inside your form tag.
2. Create a public static method in your code behind with [WebMethod] above it and add System.Web.Webservices to your usings. Add your handling code, you could update your database, increment a counter or write to a log file.
3. Add an image to your page which has an onload=”PageMethods.TheNameOfYourPageMethod” attribute.

You’re done! Pat yourself on your back and grab a latte

The Code
aspx


<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true"/>
<img src="clear.png" onload="PageMethods.HandleImageLoad()" />

Code behind

using System.Web.Services;

public partial class _Default : System.Web.UI.Page
{
[WebMethod]
public static void HandleImageLoad()
{
// handling here
}
}

ASP.NET Error Handling

Introduction
When developing a site there are bound to be occasions when despite our best efforts, errors will occur. ASP.NET has some built in facilities for handling this like custom error pages. In practice, however, we often need more information about the error so we can address the issue.

Custom Page Class
While a MasterPages might seem to be the obvious place to handle application errors, a Master Page only really behaves like a master page up to rendering then essentially acts like a user control. Also, it is quite possible that you would have several master pages in any web application. With that in mind the more logical approach would be the custom page class.

How
To make a custom page class you simply create a new class in the app_code folder which inherits from the System.Web.Page class, then, you simply override the OnError event and implement your error handling code. My weapon of choice is email, as it is pretty instantaneous and allows you to act quickly in response to potential problems (I do not operate on the ignorance is bliss development process!). Lastly you make all your aspx pages inherit from your custom page class.


using System.Web

public class CustomPage : Page
{
protected override void OnError(EventArgs e)
{
base.OnError(e);
var ex = Server.GetLastError();
var hc = HttpContext.Current;

var requestUrl = hc.Request.Url.ToString();
var emailSender = “senders email address goes here ”;
var emailSubject = "error @ site: " + requestUrl;
const string emailRecipient = "your email address goes here";

var sb = new StringBuilder();

// include information about the current web request
sb.AppendFormat("Time: {0}\n", DateTime.Now.ToString("g"));
sb.AppendFormat("URL: {0}\n", requestUrl);
sb.AppendFormat("Is HTTPS: {0}\n", hc.Request.IsSecureConnection);
sb.AppendFormat("URL Referrer: {0}\n", hc.Request.UrlReferrer);
sb.AppendFormat("Server Name: {0}\n", hc.Request.ServerVariables["SERVER_NAME"]);
sb.AppendFormat("QueryString: {0}\n", hc.Request.QueryString);
sb.AppendFormat("Platform: {0}\n", hc.Request.Browser.Platform);
sb.AppendFormat("Is Crawler: {0}\n", hc.Request.Browser.Crawler);
sb.AppendFormat("User Agent: {0}\n", hc.Request.UserAgent);
sb.AppendFormat("Supports Cookies: {0}\n", hc.Request.Browser.Cookies);
sb.AppendFormat("User IP: {0}\n", hc.Request.UserHostAddress);
sb.AppendFormat("User Host Name: {0}\n", hc.Request.UserHostName);
sb.AppendFormat("User is Authenticated: {0}", hc.User.Identity.IsAuthenticated);
sb.AppendFormat("\n\n");

var message = ex.Message;

while (ex != null)
{
sb.AppendFormat("Message: {0}\n", message);
sb.AppendFormat("Source: {0}\n", ex.Source);
sb.AppendFormat("TargetSite: {0}\n", ex.TargetSite);
sb.AppendFormat("StackTrace: {0}", ex.StackTrace);
sb.AppendFormat("\n\n");

ex = ex.InnerException;
}
var m = new MailMessage(emailSender, emailRecipient, emailSubject, sb.ToString());

var smtp = requestUrl.Contains("localhost")
? new SmtpClient("localhost")
: new SmtpClient(“smtp server address goes here usually localhost for most hosting companies”);

smtp.Send(m);
Response.Redirect(“your error url goes here”);
}
}


Explanation
In the above code quite a lot of information has been collected in addition to the basic error messages which can be very useful when trying to detect the problem. Also, the code digs down into the inner exceptions so that you see all of the bubbled exceptions. Lastly the user is redirected to a user friendly error page of your choice; this means that you are not exposing your users to the standard ASP.NET error pages which are meaningless to anyone except the developer of the application.

Generating Excel Reports from ASP.NET applications

Introduction
I see this question a lot in forums. So you made your all singing and dancing application and have beautifully styled your DataGrid, GridView or Repeater, finely tuned your report query in the database for lightening responses, there you sit marvelling your own creativity and programming prowess. That’s when you get the call from the client…

They want the data in an exportable format!!! Deafening silence, welcome to the real world, most mere mortals would rather use their favourite spreadsheet software than your blood sweat and tears creation. We developers shouldn’t take this as anything but logical choice. These programs are popular for a reason and have been around long enough that most users have already reached the tip of their learning curve. I would argue that your ability to be successful as a solution provider lies in providing solutions that fit neatly into existing ones and moreover lever and in a sense mash up tried and tested solutions and software. My question is: why re-invent the wheel?

Different Approaches
There are plenty of ways to export reports (CSV, Flat file and XML to name a few), but whether you like it or not most people use Excel or open source offerings like Open Office. Excel will open various file formats and you can trick excel by saving CSV files or even html tables with a .xls extension. If you have access to an ms office license, you can access the office com interop objects and generate spreadsheets that way. Lastly and perhaps the neatest of the solutions is to buy one of the out of the box solutions which provide standalone assemblies for generating spreadsheets like ASPOSE.

Million Dollar Question
which one of these should I use?

Million Dollar Answer
Any of them will achieve roughly the same outcome so it’s up to you.

My Choice
I have supplied solutions which export files based on the first method above, i.e. convert my data to XML or CSV content then export a file which has a .xls extension and set the Response Content Type header to excel:


Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("content-disposition", "attachment;filename=Management Report.xls");


The problem with this is that you are essentially cheating and while Excel will likely open the file, the user may get a prompt about the content when trying to open the file (something like the content not matching the extension). Also, if they were to use another program to import that file, then they would need to save it again from excel to ensure that the proper formatting is applied. I really see this as a quick and dirty approach which has its uses in some scenarios but does not really cut it for professional level solutions.

Using com interop in web applications is not my weapon of choice either and you really need to understand the concept of using unmanaged resources before you even attempt this method.

This leaves using a third party solution or writing your own (good luck to you). Third party solutions tend to be expensive, so unless your pockets are deep or your budget is large, which in the current recession is unlikely as companies are feeling the pinch, you are stuck.

The Secret
If you have ever downloaded the express versions of Visual Studio you will be asked to register the product, this entitles you to access to some pretty useful benefits in the benefit portal. One of these is SpreadSheetGear 2006, which essentially allows royalty free generation of spreadsheets from web applications (and windows apps if that is your cup of tea). It is as simple as adding a reference to the SpreadSheetGear assembly to your application, adding a using reference in your page or control then you have just to write some intuitive code to export to a file:


DataTable dt = /*get your data table here*/
IWorkbook workbook = Factory.GetWorkbook();
IWorksheet worksheet = workbook.Worksheets["Sheet1"];
IRange cells = worksheet.Range;cells.CopyFromDataTable(dt, SpreadsheetGear.Data.SetDataFlags.NoColumnHeaders);

// Auto size all worksheet columns which contain data
worksheet.UsedRange.Columns.AutoFit();

// Stream the Excel spreadsheet to the client in a format
// compatible with Excel 97/2000/XP/2003/2007.
Response.Clear();
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", "attachment; filename=" yourfilename.xls");
workbook.SaveToStream(Response.OutputStream, FileFormat.XLS97);
Response.End();


The above is a very simple example, you can produce heavily styled reports using the same assembly by selecting ranges and applying styles accordingly. Obviously there is a learning curve, but it is a clean elegant solution which generates properly formatted Excel Files that could have otherwise cost big bucks.

kick it on DotNetKicks.com

Visual Studio 2008

Microsoft Store

Microsoft Store

About Me

My Photo
David Ridgway
MCSD MCAD MCSE David has been architecting and developing software applications for the last 10 years using Microsoft technologies, more recently he has specialized in developing Web 2.0 ASP.NET applications using C#, SQL Server, AJAX, JavaScript and other development tools. When not tapping on the keyboard programming you can find him strumming guitars, banging drums and tinkling the piano keys in local bars and cafes around Osaka.
View my complete profile

Syntax

Syntax Highlighter

Expression Studio 3

Now Reading







Disclaimer

All data and information provided in THIS blog is for informational purposes only. I make no representations as to accuracy, completeness, currentness, suitability, or validity of any information on this blog and will not be liable for any errors, omissions, or delays in this information or any losses, injuries, or damages arising from its display or use. All information is provided on an as-is basis. All code may be used under the standard UIIYW BDBMIITDW license (Use It If You Want But Dont Blame Me If It Doesnt Work) :)