Archive for asp.net

Slick inline trace logging in ASP.NET

I’m going to show you a slick way to configure log4net to your trace log, and then make it extremely simple to view the trace log for a page while viewing that page. Ultimately, we’ll end up with something that looks like this:

page-tracing

It may be difficult to see from the screenshot, but I’m looking at a standard ASP.NET page, but there is tracing information at the bottom. This tracing information is the same information you would see if you configured tracing your web.config, and then used the trace.axd page. However, we’re displaying it right along with the page request. To allow tracing to be enabled with a simple URL parameter, you can add the following code into your Global.asax file:

protected void Application_BeginRequest(object s, EventArgs e)
{
	if (Context.Request.QueryString["trace"] == "true")
		Context.Trace.IsEnabled = true;
}

Of course in a public environment, it may be wise to add security or at least obfuscate the parameter. The trace information contains server information that may be helpful to someone trying to compromise the server.

Now that we have tracing information, how can we get our log messages to show up? Log4net provides an appender for logging to the ASP.NET tracing feature:

<appender name="AspNetTraceAppender"
	type="log4net.Appender.AspNetTraceAppender" >
	<layout type="log4net.Layout.PatternLayout">
		<conversionPattern
			value="[Thread #%thread] %-5level - %message%newline" />
	</layout>
</appender>

Don’t forget to wire up the adapter so that log4net knows to use it:

<root>
	<level value="DEBUG" />
	<appender-ref ref="AspNetTraceAppender" />
</root>

Now, in your code, you can simply log messages as you normally would:

_log.Debug("Loading User Data");

Conclusion

I’ve found this type of configuration very useful in my ASP.NET applications. It lets me analyze how long each portion of the page generation is taking so that I can find bottlenecks. It also motivates me to write a fair amount of logging, since I’ll see a benefit during development, as well as after deploying it into the wild.

Cloud Computing (and Azure) - Right for your site?

Everyone seems to be getting excited lately about the prospect of cloud computing. Just like many others, I get excited by the idea that I wouldn’t have to worry about adding servers to scale up. Theoretically, a guy (or girl) could make the next YouTube, in his basement, for free. However, there is one huge advantage that most people ignore, and that’s the fact that’s also perfect for a small scale website.

iStock_000004135866XSmall

I’ve tried or considered many different ways of hosting my content:

  • Shared hosting - Cheaply host your sites, but be at the mercy of their IT guy messing with your computer and rebooting it for automatic updates. Also, in my experience, the performance is terrible if your traffic spikes. They typically have hundreds of users on the same server as you, and you all get to compete for performance.
  • Dedicated hosting - This is what I use now, because it ensures that I get the full performance of a machine. The disadvantage is that I have a single point of failure, and I have to manage the machine myself.
  • Hosting from home - Yes, people actually do this. If you have a high enough upload speed it shouldn’t be too bad. The problem is that your connection typically won’t be able to handle traffic spikes. You’ll also potentially be a victim of power or Internet outages, where professional hosts would have redundant systems in place (in theory).

Now, let’s talk about cloud computing. That magical cloud that many don’t understand. There are two potentially viable cloud computing methods available right now:

  • Cloud virtual machines - Amazon’s EC2 solution is probably the most popular in this category. Basically, you can create, start, and stop virtual machines remotely. You just pay an hourly rate while the computer is running. You can even upgrade and downgrade the hardware as needed. The advantage is that you can treat the computer like a physical machine and configure and use it however you like. The disadvantage is that maintaining individual machines can be time consuming and is not necessarily part of your core business.
  • Cloud application server - Instead of creating virtual machines, a cloud application server runs your application directly. You no longer worry about the constraints of a physical machine. You application could potentially be run on dozens or hundreds of servers simultaneously. The major advantage is that there is little to no maintenance, because that is the job of the provider.

I see the cloud application server as having some of the greatest advantages. You’re free to write your application with a level of abstraction, which allows you to solve the problems you really want to solve.

One of the most well known cloud application services is the Google App Engine, which currently supports Python applications. Microsoft joined the game recently with Azure for ASP.NET.

As I mentioned, not only do application servers let your applications scale up, they let you pay only for what you use. This is great for the small to medium website’s that are stuck with bad shared hosting or difficult-to-manage dedicated hosting. The fact is that most sites get a few hundred visitors daily or less. If you start to think about how often a page is actually requested, you’ll realize that it’s not very much. Even with 500 users requesting 5 pages each in a 12 hour period can easily be handled with a very low end server from years ago.

The reason that application servers are so much more efficient than shared hosting is because they’re built from the ground up to spread the load around. This results in higher utilization, but more headroom for any single application. Shared hosting providers can move users between servers, but it’s usually a manual, and often difficult process. You’re bound to a specific physical machine (unless it’s VPS hosting), and if it goes down, so does your site.

Cloud computing is also a great way to handle traffic spikes such as the Digg effect. Let’s say that you only have 500 visitors today, but might get 10, 100, or 1000 times more in a single day. It happened to FaceStat. They went from 10,000 page views per day to almost a million because of a story on the front page of Yahoo. They had to scramble to add application servers and develop a scaling strategy immediately.

Conclusion - Cloud Application Server Benefits

Cloud computing has tremendous benefits. You no longer have to worry about scaling the underlying hardware, you simply pay as you go, and you can handle traffic spikes with ease. Once cloud computing becomes mainstream and absolutely reliable, there will be few reasons to not use it.

ASP.NET MVC Pro’s and Con’s

In our current iteration of improving our software development strategy, ASP.NET WebForms simply doesn’t fit in with the new demands of being unit testable and flexible. It comes as no surprise that ASP.NET MVC has been getting all the headlines lately. Like many others, I’ve gotten the itch to try it out. In this post I’ll talk about what I believe are the main pro’s and con’s of the new style for building web applications.

Scale

PRO - No ViewState or "surprise crap"

In traditional ASP.NET WebForms, the luxury of pretending to behave like a Windows Form comes at a price. The ViewState is a reliable way of storing all of the state information for the form. Unfortunately, due to the limitations of the web, this data needs to be a giant string inside of a hidden form field. This ends up adding a substantial number of bytes to the page, making it slower and requiring extra bandwidth. Of course the ViewState is controllable, much like the dinosaurs in Jurassic Park.

Not only is the ViewState gone, but "mystery" generated HTML is also gone. You have strict control over the HTML. This gives you great power, but with great power comes great responsibility. Use it wisely, and you will have elegant XHTML output with no surprises. You need to really know your HTML, which in today’s web world is a prerequisite anyway.

PRO - Faster server-side

It’s hard to get any real performance data about MVC, but it’s been suggested that it’s potentially 8000 times faster. Supposedly it’s due to less processing since it simply processes a "template" instead of having to build a complicated control tree. Even if it’s twice as fast, or even marginally faster, that would be significant for popular sites, or give at least a slight boost to smaller sites.

PRO - Simplified model for multiple related views

One thing that I found much easier to do with MVC was to have multiple versions of a page that displayed the same data, but in a slightly different format. For example, on my RSS package tracking website, you can look at your tracking information in a full-featured desktop browser, a mobile browser, or an RSS reader. The data being displayed is always the same, but the actual rendered output was different. If I later want to make an iPhone specific version for example, I would simply make a new view, and use an existing controller action.

PRO - Unit testable

One of the biggest challenges with WebForms was that testing was difficult. Not only was the actual output not easy to test, but the code-behind would tend to be a place that would contain important code that would never get unit tested. With both MVC and WebForms, it’s best to keep your logic away from the page, but it’s not always easy or ideal. MVC makes it simple to unit test the logic that is specific to a page. To do so, you simply test the actions in your controllers, which are regular, easy to test classes.

CON - Difficult to convert an existing site

MVC is not only a framework in this case, but a style. It is possible to convert specific pages as needed, but the cost is high. The problem is that MVC is radically different, so the benefit of converting probably isn’t worth it for most of your existing pages.

If you decide to convert your site to MVC, you may also run into issues trying to maintain existing page addresses. The specific issue I’ve ran into is that routes cannot have a trailing slash. If you want to maintain existing URL’s that have trailing slashes, there is no way to have the built-in routing generate URL’s with a trailing slash. You may end up losing one of the big advantages that MVC has to offer.

CON - Not best for SEO out of the box

I’ve mentioned some of the SEO issues before, and all but the trailing slash issue have a reasonable workaround. The routing engine likes to allow multiple addresses to render the same page, instead of enforcing a single address for each page. Luckily, as Scott Hanselman mentions, you can use a URL rewrite engine to bend it to your will. I highly recommend spending some time writing intelligent rules that perform the necessary 301 redirects, because you don’t want to take chances with SEO (Search Engine Optimization).

CON - Challenges if you’re not running IIS7

It’s clear that the last couple of versions of IIS have been major improvements over their predecessors. IIS7 takes .NET integration to an entirely new level. There is already a good page that covers the challenges you’ll face if you’re not running IIS6. I’ll just list them here for brevity:

  • .NET needs to handle all page requests to ensure that the MVC pages will be processed. This leads to bad performance of static files.
  • HTTP Compression through IIS6 doesn’t work, because the MVC pages are dynamic.
  • The homepage gives a 404 when hosted on the root of a domain.

Summary

If I needed to build a new site from scratch, and was able to use IIS7, it would be extremely likely that I would choose ASP.NET MVC. It’s a joy to work with (possibly because it’s "new"), and just makes sense. If I needed to work with an existing site, I would certainly have to consider the pro’s and con’s I mentioned above. ASP.NET MVC gives us an amazing new tool in our huge Microsoft toolbox.

Detecting mobile device user agents in ASP.NET

If you’re developing a mobile version of your website, usability should be one of your top priorities. Most sites will detect if you’re using a mobile device, and automatically redirect you to the mobile version. I’m going to show you how to do this in ASP.NET.

Detecting a mobile device based on user agent

The first issue I ran into was coming up with a reliable way to determine if the device is a mobile device based on its user agent. My first urge was to use the detection built into ASP.NET:

Request.Browser.IsMobileDevice

I immediately lost any trust in this property after it failed to correctly identify Opera Mobile on my Windows Mobile phone. I suspect something similar will happen with the iPhone.

After browsing the dozens of common mobile device user agents, I came up with this method:

public static bool IsMobile(string userAgent)
{
	userAgent = userAgent.ToLower();

	return userAgent.Contains("iphone") |
		 userAgent.Contains("ppc") |
		 userAgent.Contains("windows ce") |
		 userAgent.Contains("blackberry") |
		 userAgent.Contains("opera mini") |
		 userAgent.Contains("mobile") |
		 userAgent.Contains("palm") |
		 userAgent.Contains("portable");
}

I realize this method isn’t perfect, but I believe it will correctly identify 99% of the mobile devices out there. You simply pass in the user agent, which is easy to get:

Request.UserAgent

If you want to be a little more precise, you can come up with your own method by looking at the list of mobile agents, or you can use an updated list of mobile devices with detailed specifications. You can find that type of list here.

Have a better way to do it? Have a common device that my method doesn’t work for? Please let me know in the comments!

Response.Redirect and Output Caching Trouble

I ran into an interesting issue with output caching. If you have a page that uses output caching and that page conditionally sends a redirect response, you need to be careful.

Redirect

Let’s say that you have a page that redirects to the mobile version of your website if they have a mobile browser. Let’s suppose that you’re using a standard, generic output caching directive:

<%@ OutputCache Duration="300" VaryByParam="*" %>

When the page renders, the rendered HTML will be cached. The next incoming request will get the cached HTML, and the page rendering and code execution will be completely avoided. If you get a visitor that is using a mobile device, your code to determine if the request should be redirected will never get executed.

Here is another way to look at this scenario:

  • Request #1: Page makes the decision to redirect to another page.
    • Result: Page not cached.
  • Request #2: Page makes the decision to render HTML.
    • Result: This HTML is now rendered and cached.
  • Request #3: Doesn’t matter.
    • Result: The cached HTML from request #2 is rendered, even if the page should be redirecting.

There are a couple of workarounds to keep your redirects working:

Turn off caching

Of course the simplest option is to simply turn of output caching for the page that needs to perform a conditional redirect. It goes without saying that you’ll lose all the wonderful advantages of output caching.

Use a caching seed

Another option is to write some code in your applications "GetVaryByCustomString" method that determines if it’s a request that will be redirected. If so, a unique value is returned. This forces the page to re-render because it is not found in the page cache. Unfortunately, the code in your custom string method may get complicated very quickly.

If you’re lucky, you’ll be making the redirect decision based on something that can be automatically used to vary the output caching. For example, if your page redirects based on a URL parameter, you can simply use the VaryByParam="*" in your output cache directive (or specify the specific parameter). Keep in mind that each set of parameters supplied to the page will result in a separate cache entry. This could lead to excessive memory usage for some pages.

Use fragment caching

Of course you could avoid using output caching on the page itself. You simply use the page as a place for your redirect logic, not the content generation. Then, put the actual page generation logic and content into a UserControl. When you use output caching on that control, it won’t affect the redirect logic in the page. The disadvantage of this technique is that you may have to do extra work separating your content into controls. You also won’t get the full benefit of caching since some of the control tree still needs to be processed, and some parts of the page such as the MasterPage will not get cached.

Conclusion

Remember, this is only an issue if the page being cached makes a decision to redirect. If the page always performs a redirect, the page will not be cached (why are you using output caching then?). Obviously this issue isn’t unique to Response.Redirect, but it is an issue you should be aware of.

One mischievous aspect of this issue is that if you test your site in a certain order, you won’t see a problem. For example, if you first view the page under the circumstances needed to make it redirect, it will work. You’ll only see the issue if you cause it to not redirect, and then try to get it to redirect.