Hacking .NET and Startups

How to Securely Verify and Validate Image Uploads in ASP.NET and ASP.NET MVC

One of the more interesting things I had to do as part of building XAPFest was handle bulk image uploads for screenshots for applications and user / app icons. Most of the challenges here are UI-centric ones (which I resolved using jQuery File-Upload) but the one security challenge that remains outstanding is ensuring that the content uploaded to your servers is safe for your users to consume.

Fortunately this problem isn't too hard to solve and doesn't require much code in C#.

Flawed Approaches to Verifying Image Uploads

Here's what I usually see when developers try to allow only web-friendly image uploads:

  1. File extension validation (i.e. only allow images with .png, .jp[e]g, and .gif to be uploaded) and
  2. MIME type validation.

So what's wrong with these techniques? The issue is that both the file extension and MIME type can be spoofed, so there's no guarantee that a determined hacker might not take a js. file, slap an extra .png extension somewhere in the mix and spoof the MIME type.

Stronger Approach to Verifying Image Uploads: GDI+ Format Checking

Every file format has to follow a particular codec / byte order convention in order to be read and executed by software. This is as true for proprietary formats like .pptx as it is for .png and .gif.

You can use these codecs to your advantage and quickly tell if a file is really what it says it is - you quickly check the contents of the file against the supported formats' codecs to see if the content fits into any of those specifications.

Luckily GDI+ (System.Drawing.Imaging), the graphics engine which powers Windows, has some super-simple functions we can use to perform this validation. Here's a bit of source you can use to validate a file against PNG, JPEG, and GIF formats:

using System.Drawing.Imaging;
using System.IO;
using System.Drawing;

namespace XAPFest.Providers.Security
    /// Utility class used to validate the contents of uploaded files
    public static class FileUploadValidator
        public static bool FileIsWebFriendlyImage(Stream stream)
                //Read an image from the stream...
                var i = Image.FromStream(stream);

                //Move the pointer back to the beginning of the stream
                stream.Seek(0, SeekOrigin.Begin);

                if (ImageFormat.Jpeg.Equals(i.RawFormat))
                    return true;
                return ImageFormat.Png.Equals(i.RawFormat) 
|| ImageFormat.Gif.Equals(i.RawFormat);
                return false;


All this code does is read the Stream object returned for each posted file into an Image object, and then verifies that the Image supports one of three supported codecs1.

This source code has not been tested by security experts, so use it at your own risk.

If you have any questions about how this code works or want to learn more, please drop me a line in the comments below or on Twitter.

Bonus: How Do I Make Sure Files Are below [X] Filesize?

Since I had this source code lying around anyway, I thought I would share it: 

public static bool FileIsWebFriendlyImage(Stream stream, long size)
            return stream.Length <= size && FileIsWebFriendlyImage(stream);

Super-simple, like I said, but it gets the job done. Express the maximum allowable size as a long and compare it against the length of the stream


1The other important catch to note here is that I move the Stream's pointer back to the front of the stream, so it can be read again by the caller which passed the reference to this function.

If you enjoyed this post, make sure you subscribe to my RSS feed!

.NET Culture Shock: Why .NET Adoption Lags Among Startups

July 3, 2010 11:48 by Aaronontheweb in .NET, Startup // Tags: , , // Comments (108)

One of the other things I took away from Code Camp was a bit of .NET culture shock. As you can tell by glimpsing around on this blog, I am somewhat enamored with the idea of starting my own business. I’m a natural entrepreneur and it is my wont to think about startups constantly.

That being said, I’ve always wondered why a platform as widely adopted and supported as .NET isn’t more visible in startup culture. Many major open source  platforms and languages have very visible and vocal presences in the startup community, everything from mainstays like Python and PHP to even the more obscure and specialized ones like Clojure and Hadoop.

.NET on the other hand is conspicuously absent from the startup conversation despite the fact that it is a singularly larger platform than any of the others.

It’s like there’s a silent majority among the development community that just tinkers away on its own projects without even occasionally raising its hands and saying “here’s something clever and unique we did with this platform that no one else has done before.”

It’s somewhat tragic for the .NET community too – because the perceived lack of sex-appeal on the surface doesn’t match the reality of what the platform is capable of.

Just take a brief moment to peruse through CodePlex for more than a couple minutes and you’ll find thousands upon thousands of examples creative open source projects all built in .NET.

And in the startup space there actually are a number of .NET-based startups making it big, including this week’s Hacker News / Social Media darling Woot. But why oh why isn’t there a louder .NET voice in the startup community? Why aren’t there developers from Woot working with developers from StackOverFlow (also implemented in .NET) to encourage more startups to use the extensive .NET stack to create new and exciting products and services?

And most importantly, why aren’t there more startups adopting .NET?

It’s All about the Enterprise

I’ve heard all sorts of lame answers to this question before: “platform lock-in,” “no open standards,” “licensing costs,” and none of them pass the test of objective reality – yes, those are issues that might prevent some developers from adopting .NET in the startup space, but not enough to bar virtually all of them from using .NET, arguably the most comprehensive and versatile platform with the best tools and the best support.1

At Code Camp I think I finally figured out why this is: it’s the culture of the .NET community itself, not anything specific to the platform or the architecture which supports it.

.NET culture is centered around the concerns of  the enterprise – the large already-established businesses in the economy, not plucky up-and-coming startups. The Promotion PitAnd when I say “culture,” I’m not talking about the development tools – I’m talking about where the hearts and minds of the developers who use the .NET platform are. I’m talking about the blogs and media sources .NET developers read. I’m talking about the networks where .NET developers contribute and the substance of their conversations.

Most of the developers I met developed portals for giant healthcare providers with thousands of employees, worked on legacy code whose lifespan could be measured in decades, worked in teams with hundreds and even thousands of programmers, and lived in ecosystems ruled by large bureaucracies. These are problems to which few if any developers for startups can relate.

That’s why so many of the talks at Code Camp were staked around RAD methodologies for developing internal projects, coding standards, enterprise architecture, and other things that matter to developers who work in giant ecosystems.

And who can blame Microsoft for catering to the enterprise market – that’s where the money is! No one ever became rich selling high-end development tools to a handful of capital-starved, small companies.

However, the consequences of the .NET community’s enterprise-centric culture is that the startup community and the .NET community don’t overlap as much as they do for other technologies.

As a result, developers working for startups and even the startup founders themselves don’t get much exposure to .NET and don’t think of it as an applicable tool for their purposes.

The flipside is that many .NET developers who want to work for hot startups don’t have as many opportunities to do so unless they abandon the platform for a more “startup-friendly” one or start a company themselves.

So what do the members of the .NET community fuss over? They worry about supporting legacy systems, building enterprise architectures which can service multiple departments, they worry about large systems for supporting in-house business processes, and they worry about satisfying the needs of stakeholders throughout their companies.

.NET developers in general, worry about architecture in order to support systems.

Members of the startup community fuss over a very different set of issues – they’re their own stakeholders, they worry about concurrency, they worry about scalability, they worry about user experience design, they worry about supporting multiple clients and browsers, and they worry about how their designs will impact their bottom line.

Startup developers in general, worry about architecture in order to support products.

See the difference? .NET is perfectly capable of fulfilling the needs of product designers and startups, but comparatively little2 of the .NET culture, literature, and conversation is product-centric – instead the majority of it is structured around using .NET to support the needs of the business, not building the business’ products itself!

But It Doesn’t Have to Be

One thing that should be clear here is that any platform, not just .NET, can be used as a platform for building enterprise technology and for building new products. The platforms don’t often dictate their use – that’s the work of the people who develop on them.

If Microsoft wants to make a splash in the startup scene with .NET, and I have every reason to believe they do, then they need to do a better job evangelizing .NET’s capacity from a holistic new service / new product / new business perspective and not just for the enterprise.

Enterprise and startups aren’t mutually exclusive – they’re just different stages in the evolution of software, and there’s no reason why the startup community shouldn’t look at .NET as an attractive starting point for a new business.

The next article I’m going to write on this subject will cover why it’s a good idea for Microsoft to have .NET adopted more readily by the startup community.

1I realize “best” is a subjective term, but please do your best to just stick with me here. I’m not trying to trash Eclipse, XCode, NetBeans, or EMACS, but just face it: Visual Studio destroys those in any feature set-to-feature set comparison.

2Again, this is an observation based on my experience with the .NET community thus far. I'm always on the lookout for any exposure to people who use .NET in a startup setting.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Lessons from Code Camp 2010

July 3, 2010 07:22 by Aaronontheweb in General // Tags: , // Comments (0)

This time last weekend I was in the middle of the second session of Southern California Code Camp. Ever since I came to the realization that no man is an island and I’m going to ultimately need to work with other programmers in order to be successful in this business, I’ve made an effort to attend as many geeky networking events as I can.

Code Camp was a fantastic learning experience for someone who’s as interested in the .NET platform as I am. During Code Camp I was introduced to:

  • Silverlight 4;
  • Silverlight for Windows Mobile Phone 7;
  • ASP.NET MVC2, which I used this past week to build The Great Wall of Geeks;
  • .NET 4.0 multithreading (Parallel.For, Task engine etc…);
  • .NET coding standards; and
  • Agile Development and working with legacy code.

By far and away the best session for me was the Pair Programming / Agile Development Dojo, namely because I got my first taste for Agile development and the inherent value of rapid prototyping and test driven development was obvious.


How to Query a User's del.icio.us Feed with RestSharp

June 14, 2010 12:26 by Aaronontheweb in .NET, Del.icio.us // Tags: , , , , , // Comments (2)

I've been meaning to give RestSharp a go since I first started using Hammock in my startup project's codebase, just because I had heard some good things about RestSharp's auto-parsing capabilities.

This weekend I cobbled together a small example using del.icio.us' RSS feeds (not to be confused with its draconian REST API) for users and RestSharp performed magnificently, although its POCO -> XML Element mapping process requires a lot of experimentation before you get it just right.

Here's an example RSS feed for my personal del.icio.us account:

<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://web.resource.org/cc/">
    <description>bookmarks posted by Aaronontheweb</description>
    <atom:link rel="self" type="application/rss+xml" href="http://feeds.delicious.com/v2/rss/Aaronontheweb?count=2"/>
      <title>Windows Presentation Foundation (WPF) Dialog Boxes Overview</title>
      <pubDate>Fri, 04 Jun 2010 23:48:12 +0000</pubDate>
      <guid isPermaLink="false">[REMOVED]</guid>
      <source url="http://feeds.delicious.com/v2/rss/Aaronontheweb">Aaronontheweb's bookmarks</source>
      <description>How to use dialog boxes in WPF (for WPF noobs like myself.)</description>
      <category domain="http://delicious.com/Aaronontheweb/">.net</category>
      <category domain="http://delicious.com/Aaronontheweb/">wpf</category>
      <category domain="http://delicious.com/Aaronontheweb/">dialogs</category>
      <category domain="http://delicious.com/Aaronontheweb/">tutorial</category>
      <category domain="http://delicious.com/Aaronontheweb/">nullable</category>
      <category domain="http://delicious.com/Aaronontheweb/">c#</category>
      <title>Developer's Guide: Data API Protocol - YouTube APIs and Tools - Google Code</title>
      <pubDate>Mon, 31 May 2010 22:43:47 +0000</pubDate>
      <guid isPermaLink="false">[REMOVED]</guid>
      <source url="http://feeds.delicious.com/v2/rss/Aaronontheweb">Aaronontheweb's bookmarks</source>
      <description>Finally figured it out - how to sign all requests with my API key using a querystring. So simple, yet so difficult.</description>
      <category domain="http://delicious.com/Aaronontheweb/">youtube</category>
      <category domain="http://delicious.com/Aaronontheweb/">API</category>
      <category domain="http://delicious.com/Aaronontheweb/">key</category>
      <category domain="http://delicious.com/Aaronontheweb/">Google</category>
      <category domain="http://delicious.com/Aaronontheweb/">gdata</category>

The best way to utilize RestSharp to parse any sort of API response, whether it's custom REST XML, JSON, Atom, or RSS, is to first take a look at the raw response format and then to try to model a set of Data Transfer Objects (DTOs) which contain the response format elements you want to actually use in your application. Your DTOs just need to be simple POCO objects for this to work, but there are a set of POCO-XML Element matching rules you need to observe if you're using RestSharp's default deserializer - you can read them here.

Here are the classes that I modeled for this RSS format:

public class RssFeed
    public string Version { get; set; }
    public RssChannel Channel { get;set; }

public class RssChannel
    public string Title { get; set; }
    public string Description { get; set; }
    public string Link { get; set; }
    public RssItems Item { get; set; }

public class RssItems : List<item>{}

public class item
    public string Title { get; set; }
    public string Description { get; set; }
    public string Link { get; set; }
    public string Author { get; set; }
    public string Comments { get; set; }
    public string PubDate { get; set; }

This diagram explains how these DTO classes map to the del.icio.us RSS format:

del.icio.us restsharp POCO class to XML document mapping

ProTip: Handling Lists of XML Elements with POCO Classes

One thing that's a bit tricky is handling lists of XML elements, such as the <item> elements in this case. In order for RestSharp to deserialize them, you need create a List<T> object where the name of class T matches the name of the listed element, which is why my class name is item in this case.

Once you have your POCO classes in order, then you need to actually make requests against the del.icio.us feed for a particular user. Here's my code for doing that:

public class DeliciousRequest
    public const string DeliciousFeedBase = @"http://feeds.delicious.com/v2/rss/";

    private RestSharp.RestClient _client;

    public DeliciousRequest()
        this._client = new RestClient
                              BaseUrl = DeliciousFeedBase

    public RssFeed GetBookMarksForUser(string username)
        var request = new RestRequest {RequestFormat = DataFormat.Xml, Resource = username};
        var response = this._client.Execute<RssFeed>(request);
        return response.Data;


All RSS feeds for del.icio.us users can be found using http://feeds.delicious.com/v2/rss/{USERNAME}, therefore you can understand why the RestClient's BaseURL and the RestRequest's Resource arguments are defined as they are. Once you have your RestRequest defined, you simply call the client's Execute<T> method where T is the type of your POCO DTO class.

And that's it - RestSharp is easy, and I look forward to creating some more examples with it down the road.

More RestSharp Examples:

If you enjoyed this post, make sure you subscribe to my RSS feed!

How to Use the Microsoft Enterprise Library Validation Application Block, Part 1

All user input is evil, and you know it. Since the inception of .NET, ASP.NET developers have had access to the ASP.NET Validators Control Library, which made the previously tedious process of validating form input simple and in many instances, trivial. Microsoft's Enterprise Library makes this familiar ASP.NET functionality available at the object level in your applications via the Validation Application Block, which I've been using throughout some of my new projects.

It can take a while to get familiar with the Validation Application Block, so my goal here is to show you how to quickly get started with it using attribute-based validation, which in my opinion is the simplest way to implement validation. By the time you're doing reading this you'll know how to use built-in validators such as the RangeValidator, RegexValidator, DateTimeRangeValidator, and so forth.

Introduction to the Validation Application Block Built-in Validators

What can the Validation Application Block do, exactly? Well, here's a list of the validators that are built-in to the Validation Application Block:

  • The NotNullValidator which requires an instantiated data member.
  • The RangeValidator and the DateTimeRangeValidator, which check to see that a data member's value falls within a specified set of boundary conditions.
  • A slew of validators for testing strings:
    • The StringLengthValidator for testing that a string's length falls within a specified set of boundary conditions.
    • The RegexValidator and the ContainsCharactersValidator, both of which test that a string contains a specified target sub-string or expression.
    • The TypeConversionValidator, which tests to see if a string can be converted to some other type.
  • Validators for testing the comparative values of fields, such as the PropertyComparisonValidator and the RelativeDateTimeValidator.
  • The DomainValidator and the EnumValidator, which checks to see that a value falls within a specified set of acceptable values.
  • The ObjectValidator and the ObjectCollectionValidator, which are used to invoke validation methods on data members which are also validation-enabled objects.

In addition to these built-in validators the Validation Application Block also includes methods for creating user-defined validators and for composing validators into ValidatorCompositions which can process more complex validation rules.

How to Add the Validation Application Block to a Visual Studio Project

Before you worry about how to start adding validators to all of your business objects, you need to include the necessary assemblies into your Visual Studio / Visual [X] Express projects. After you've downloaded and installed the Enterprise Library 5.0 or *Enterprise Library 4.1 binaries onto your system, open your existing Visual Studio Project or create a new one. Open the Solution Explorer, expand the References folder, right click on the References folder and click on Add Reference

Select the following two assemblies (typically they'll be installed to your system's GAC so you won't need to go hunting for them) - Enterprise Library Shared Library and Enterprise Library Validation Application Block. The Validation Application Block depends on Shared Library (as do many other components in the Enterprise Library), and you'll run into some run-time errors without it included in your project's References folder.

If you're designing a WinForms or an ASP.NET application, you may want to include the special Validation Application Block WinForms Integration or Validation Application Block ASP.NET Integration assemblies, but if you're designing validation rules for individual business object classes and not presentation-layer events, you may not need them.

Example: Using Built-in Validators for Validating an Address

I'm going to end this post with a simple example which will show you how to get started using the Validation Application Block's attribute-based validators, and I'll expand on this in subsequent posts. We're going to work with a simple class which contains an address based in the United States:

public class USAddress
    public string RecipientName { get; set; }
    public string Street { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }

We know that addresses based in the United States need to comply with the following business rules:

  1. All of these fields must be filled in;
  2. A street must contain a street name and a street number;
  3. A state code must be two characters in length; and
  4. A zip code contains exactly five or nine digits.

 So, let's examine how we can use some validators to ensure that this business object enforces these business rules. The first step is to ensure that our source code references the correct namespace:

using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

 Next, let's go ahead and enforce business rule #1 - all address fields must be filled in. We can accomplish by decorating each field with NotNullValidator attribute:

using System;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

namespace Business_Entities
    public class USAddress
        public string RecipientName { get; set; }

        public string Street { get; set; }

        public string City { get; set; }

        public string State { get; set; }

        public string ZipCode { get; set; }

Let's see if this works. Here's some simple code we can use to test the validators by calling the Validator.Validate() method against an instance of this class.

using System;
using System.Text;
using Business_Entities;
using Microsoft.Practices.EnterpriseLibrary.Validation;

namespace Basic_Validation__Console_
    class Program
        static void Main(string[] args)
            //Create a blank test address
            USAddress testaddress = new USAddress();

            //Create a new validator using the ValidationFactory method
            Validator validator = ValidationFactory.CreateValidator<USAddress>();
            ValidationResults results = new ValidationResults();
            validator.Validate(testaddress, results);

            Console.Write("Is the test address valid? {0}", results.IsValid);
            //Stop the console screen from disappearing immediately.

And what happens when we run this test code? 

Smells like success to me. Let's re-run this test using a valid address.

//A real(ish) test address
USAddress testaddress = new USAddress();
testaddress.RecipientName = "Bob Jones";
testaddress.City = "Beverly Hills";
testaddress.State = "CA";
testaddress.Street = "1205 Rodeo Drive";
testaddress.ZipCode = "90210";

And the result is: 

Looks like the NotNullValidator is working as intended. But wait a minute, how did this ValidationFactory.CreateValidator() method know how to create a Validator object that properly validates any instance of a USAddress object?

Because we decorated the USAddress class with one or more Validator attributes, the underlying Validation Application Block library automatically implements and registers a Validator class designed to support the USAddress class. Internally, the Validation Application Block uses an instance of Unity to resolve a custom validator for the USAddress class on-the-fly.

Let's enforce some of the other business rules, starting with the state code.

[StringLengthValidator(2, RangeBoundaryType.Inclusive, 2, RangeBoundaryType.Inclusive)]
public string State { get; set; }

As you can see I've added a StringLengthValidator in addition to the NotNullValidator that was already in place (yes, you can add more than one Validator attribute to a field.) I've specified the following parameters for this validator:

  1. lowerBound = 2
  2. lowerBound RangeBoundaryType = Inclusive (meaning that this value is included in the range of acceptable string length values)
  3. upperBound = 2
  4. upperBound RangeBoundaryType = Inclusive (this value is also included in the range of acceptable string length values)

There are three possible range boundary types:

  1. Inclusive, which is the equivalent of [] in traditional mathematical syntax;
  2. Exclusive, which is the equivalent of () in traditional mathematical syntax; and
  3. Ignore, which is the equivalent of (infinity, or infinity) in traditional mathematical syntax.

Now the next change we need to make is to check for a valid zip code, which can be either 9 or 5 digits. I'm going to do this using a RegexValidator - another way to do this is to create an ValidatorComposition (an "Or" type as opposed to an "And" type) with two different string length validators. Here's what our RegexValidator looks like:

[RegexValidator(@"^(\d{5}-\d{4}|\d{5}|\d{9})$|^([a-zA-Z]\d[a-zA-Z] \d[a-zA-Z]\d)$")]
public string ZipCode { get; set; }

Hat tip to Microsoft's Patterns & Practices group for providing me with the regular expression for validating US zip codes.

Now, our source code for testing this validation has not changed one bit - all of the changes to the validator for the USAddress class occur behind the scenes. Once I recompile my class library and re-run the test I should get a "validation successful" message back from the console: 

Well hell yeah, that'll do it! If I wanted to validate the last business rule (the street address must contain both a street name and number,) I could write another RegexValidator for that and hook it up in much the same way as my RegexValidator for zip codes. And that's all it really takes to get started with the Microsoft Enterprise Library Validation Application Block. In my next article on the subject I'll include some examples on how / when you should use ObjectValidators and why they're so useful.

*Although the latest version of the Validation Application Block is version 5.0, my example code uses Enterprise Library version 4.1, namely because my individual development environment has some issues with the Validation Application Block 5.0 and the GAC. Given that there are no major syntactical differences between the two versions, I'm going to do what any economical programmer would do and use what works instead of dicking around with configuration files, assembly directories, and things that are frankly tangential to developing applications.

If you enjoyed this post, make sure you subscribe to my RSS feed!

How to Test Regular Expressions in .NET without Giving Yourself Migraines

May 17, 2010 05:56 by Aaronontheweb in .NET // Tags: , // Comments (1)

I write a lot of parse-heavy applications, so naturally I spend a fair amount of my development time writing and testing regular expressions. Regular expressions are one of those programming constructs where you always have a clear idea of what you need to do but you work with them just infrequently enough that you can never actually remember the exact syntax. And if you're like me, this means a multi-hour regex 101 refresher until you get it right.

Rather than testing my regular expressions in the middle of a unit test or in some temporary debug code, I've started using .NET Framework Regular Expressions Demo (scroll down to the bottom) provided by Regular-Expressions.info. It's a simple Windows Forms application that allows you to run quick regex tests using the System.Text.RegularExpressions engine, which is nice because it's actual regular expressions engine you'll be using in your .NET production code.

Let me show you how it works using a couple of examples. Suppose we've written the following regular expressions (in C#) for testing the validity of a user's email address:

string EmailRegex1 = @"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b";
string EmailRegex2 = @"^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$";
string EmailRegex3 = @"^[\w-]+@([\w-]+\.)+[\w-]+$";

We need to verify that these regular expressions work in all of our use cases:

  1. firstname@email.com
  2. fistname.lastname@email.com
  3. firstname@email.subdomain.com
  4. first-name@email.com
  5. Etc...

Let's see how we can do accomplish this using the .NET Regex Demo: 

Plugin your regular expression and your test case into their appropriate fields and hit the match test button.


Whoops! Our test case failed? Perhaps it's because the regex doesn't account for case - I'll re-run the test with the System.Text.RegularExpressions' "Case insensitive" option set to true this time.


That did the trick - so if I wanted to use this particular regex in my production code, I'd just need to remember to set the Regex engine's IgnoreCase option to true:

string EmailRegex1 = @"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b";

Regex r = new Regex(EmailRegex1, RegexOptions.IgnoreCase);

This is way better than testing regular expressions through NUnit tests and debug code.

Download (.zip) http://www.regular-expressions.info/download/csharpregexdemo.zip 

If you enjoyed this post, make sure you subscribe to my RSS feed!

BlogEngine.NET Extension - Remind Your Readers to Subscribe to Your RSS Feed with SubscribeRemind

May 15, 2010 17:55 by Aaronontheweb in BlogEngine.NET // Tags: , , // Comments (1)

One of my favorite WordPress plugins dating all the way back to when I first started blogging is Subscribe-Remind (WordPress) - it simply appends a small RSS subscription reminder to the footer of every blog entry for your readers! The reminder reads something like this:

If you enjoyed this post, make sure you subscribe to my RSS feed!

Simple enough, right? I've made a port of this popular WordPress plugin for BlogEngine.NET, SubscribeRemind, which does exactly the same thing as its WordPress counter part. It appends a small subscription reminder at the footer of every blog post using the RSS feed specified through the BlogEngine.NET settings.

If you're using an alternate RSS address (i.e. FeedBurner), the extension will automatically use that one as the target - it uses whatever RSS feed target you've specified in your BlogEngine.NET settings. 

I've found that adding an RSS susbscription reminder at the footer of all of my blog entries has historically increased my total number of subscribers, so I highly recommend that you add this Extension to your blog!

Download: SubscribeRemind1.1.zip (1.66 kb) 

UPDATE for BlogEngine.net 2.0: SubscribeRemindExtensionForBlogEngine2.0.zip (1.65 kb)

Customizing the Reminder 

You can change the reminder call to action yourself using the BlogEngine.NET extensions manager. Simply go to the Extensions page and click on the "edit" button for SubscribeRemind's settings:  

If you want to change the reminder call to action / message that appears at the bottom of every blog post, you can simply modify the value shown below:

Hit the update button after you've made your changes and placed the [link] [/link] tags around your desired anchor text.


The instructions included with the ExtensionsManager are straight-forward.

Download: SubscribeRemind1.1.zip (1.66 kb) 

UPDATE for BlogEngine.net 2.0: SubscribeRemindExtensionForBlogEngine2.0.zip (1.65 kb)

If you have any questions, suggestions, or comments about SubscribeRemind, please leave them below and I'll answer them as soon as I can.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Popular .NET Libraries

May 14, 2010 15:31 by Aaronontheweb in .NET // Tags: , // Comments (0)

I added a page a list of the .NET client libraries I use in my production and development code. Some of these, like NUnit and NLog, are pretty well-known to grizzled .NET developers, but others like the HTML Agility Pack and Hammock are not nearly as well-known as they should be given how powerful and extensive they are.

Check out my list of .NET client libraries and let me know if you have any suggestions.

If you enjoyed this post, make sure you subscribe to my RSS feed!



My name is Aaron, I'm an entrepreneur and a .NET developer who develops web, cloud, and mobile applications.

I left Microsoft recently to start my own company, MarkedUp - we provide analytics for desktop developers, focusing initially on Windows 8 developers.

You can find me on Twitter or on Github!

Recent Comments

Comment RSS

Sign in