personal, code 0 comments suggest edit

UPDATE: We moved the date to February 24th.

The stars at night, are big and bright – clap clap clap clap – deep in the heart of Texas!

Hold onto your ten gallon hats, I’m visiting Texas for the first time! I’m very excited to visit the second largest state in the union. ;)

austin The purpose of my trip is to meet with some developers at Dell doing interesting things and to give a talk there as well.

But since I’ve heard such good things about the vibrant tech community in Austin, I am trying to make the most of my short trip. On Wednesday, February 24, I’ll be speaking at Austin .NET User Group meeting at 7:00 PM CSTat the Microsoft offices in Austin.So be sure to come by and say hello.

We moved it to the 24th so if you were planning on attending Martin Fowler’s talk on February 25th, you can see both! Unfortunately for me, I was hoping to see Martin speak, but I saw that they’ve closed registration.

I’m also going to visit my good friends at Headspring as well as Dovetail Software to jabber about technology and see what cool things they’re doing with ASP.NET and ASP.NET MVC.

And of course, a trip to Austin wouldn’t be complete without a night out on the town with Bellware. I expect chaos. ;)

Tags: austin, texas, .net user group 0 comments suggest edit

The ASP.NET Team is still looking for that QA person out there who shares our passion for technology and improving the means by which software is made.

Keep in mind that the QA position on our team is not someone who mindlessly follows a script hoping by sheer random luck to find bugs. Oh no no no my friends.

This is considered a software development position in which you will be responsible for improving the processes and tools we have in place for ensuring quality software. You’d be involved in improving the quality of all phases of product development as a valued member of a feature crew. Think broadly about the idea of software quality. Your role is to question whether we’re building the right product as much as it is to test the product once it is built.

Matt Osborn, a member of the ASP.NET MVC feature crew has a description of the position.

That’s right you read the title right the ASP.NET QA team is once again hosting ninja try outs. We are looking for someone who is able to help evolve the team processes, improve our tooling, and join us in the trenches as we test one of the best technologies out there. Overall the team is responsible for ASP.NET WebForms, ASP.NET MVC, Microsoft AJAX, and a whole slew of other technologies. Our technologies can be found in numerous large scale web sites such as,

Once again we would like to find someone that shares our passion for our technology and our trade and someone that has spent sometime in the trenches. So if this sounds like something you’re interested in polish your nun chucks, practice your disappearing skills, and slice your way through our job posting. In the meantime while your sword is out for sharpening send Mark Berryman (one of our managers) an email.

PS: If you listen to the Coding QA podcast you can get a good feel for what it is like being the frontline testing ninjas for ASP.NET. We had a great turn out last time and please feel free submit your resume again it can’t hurt.

Keep in mind we’re not looking for “test” ninjas as in “sample” ninjas. We’re looking for the real deal, brimming with throwing stars of bug finding. Ok, the analogy breaks down a bit there. But you get the picture.

And before I forget, here’s the direct link to the job description on the Microsoft careers site.

subtext, code 0 comments suggest edit

This blog is experiencing technical difficulties. Do not adjust your browser.

Hi there. If you’ve tried to visit this blog recently you might have noticed it’s been down a lot in the last two days. My apologies for that, but hopefully you found what you needed via various online web caches.

I’ve been dogfooding the latest version of Subtext and as CodingHorror points out, dogfood tastes bad.

I’ve done a lot of testing on my local box, but there are a class of bugs that I’m only going to find on a high traffic real site, and boy have I found them!

Some of them might be peculiar to my specific data or environment, but others were due to assumptions I made that were wrong. For example, if you use ThreadPool.QueueUserWorkItem to launch a task, and that task throws an unhandled exception, that can bring your entire App Domain down. Keep that in mind if you think to use that method for a fire-and-forget style task.

In any case, the point of this post is to say that we’re not going to release the next version of Subtext until it’s rock solid. My blog going down occasionally is the cost I’m incurring in order to make sure the next version of Subtext is a beast that won’t quit.

code 0 comments suggest edit

UPDATE: 12/30 I had transposed the rgb colors. I corrected the function.

I’ve been distracted by a new jQuery plugin that I’m writing. The plugin has certain situations where it sets various background and foreground colors. You can have it set those styles explicitly or you can have it set a CSS class, and let the CSS stylesheet do the work.

color-wheelI’m writing some unit tests to test the former behavior and ran into an annoying quirk. When testing the color value in IE, I’ll get something like #e0e0e0, but when testing it in FireFox, I get rgb(224, 224, 224).

Here’s a function I wrote that normalizes colors to the hex format. Thus if the specified color string is already hex, it returns the string. If it’s in rgb format, it converts it to hex.

function colorToHex(color) {
    if (color.substr(0, 1) === '#') {
        return color;
    var digits = /(.*?)rgb\((\d+), (\d+), (\d+)\)/.exec(color);
    var red = parseInt(digits[2]);
    var green = parseInt(digits[3]);
    var blue = parseInt(digits[4]);
    var rgb = blue | (green << 8) | (red << 16);
    return digits[1] + '#' + rgb.toString(16).padStart(6, '0');

Now, I can compare colors like so.

equals(colorToHex('rgb(120, 120, 240)'), '#7878f0');

I hope you find this useful. :)

code 0 comments suggest edit

UPDATE (12/26): I updated this post to use the href instead of the rel attribute

It’s Christmas day, and yes, I’m partaking in the usual holiday fun such as watching Basketball, hanging out with the family and eating our traditional Alaskan king crab Christmas dinner. But of course it wouldn’t be a complete day without writing a tiny bit of code!


Today I’ve been working on improving the UI here and there in Subtext. One common task I run into over and over is using an anchor tag to trigger the hiding of another element such as a DIV. It happens so often that I get pretty tired of hooking up each and every link to the element it must hide. Being the lazy bastard that I am, I thought I’d try to come up with a way to do this once and for all with jQuery and a bit of convention.

Here’s what I came up with. The following HTML shows a DIV element with an associated link that when clicked, should hide the DIV.

<div id="hide-this">
    This here DIV will be hidden when you click on 
    the link
<a href="#hide-this" class="close">This is the link that hides the DIV</a>

The convention here is that any anchor tag with a class “close” is going to have its click event hooked up to close another element. That element is identified by the anchor tag’s rel href attribute, which contains the id of the element to hide. This was based on a suggestion by a couple of commenters to the original version of this post where I used a rel attribute. I like this much better for two reasons:

  • The href value is a hash which is already in the correct format to be a CSS selector for an ID.
  • I’m not using the href value in the first place, so might as well make use of it.

Yeah, this is probably an abuse of this attribute, but in this case it’s one I can live with due to the benefits it produces. The rel attribute is supposed to define the relationship of the current document to the document referenced by the anchor tag. Browsers don’t do anything with this attribute, but search engines do as in the case with therel value of “no-follow”~~.~~

However in this case, I feel my usage is in the spirit of this attribute as I’m defining the relationship of the anchor tag to another element in the document. Also, search engines are going to ignore the value I put in there unless the id happens to match a valid value, so no animals will be harmed by this.

Now I just need a little jQuery script to make the magic happen and hook up this behavior.

$(function() {
    $('a.close').click(function() {
        return false;

I happened to choose the slide up effect for hiding the element in this case, but you could choose the hide method or fadeOut if you prefer.

I put up a simple demo here if you want to see it in action.

I’m just curious how others handle this sort of thing. If you have a better way, do let me know. :)

Tags: jQuery, JavaScript

personal 0 comments suggest edit

Just wanted to wish you all a Merry Christmas, Happy Holidays, or a Happy whatever you are celebrating at this time of year. I hope you are spending it well with family and friends! :)

As you can see, I’m still hard at work watching the kids on paternity leave.

Playing Call of Duty Modern Warfare 2 With

My brother is a drug dealer and the name of the drug is Call of Duty: Modern Warfare 2 for the X-Box 360. I’m totally hooked right now, and I don’t usually get so hooked on games.

At least I am managing to still get some fresh air outside and enjoy the weather. Here I’m walking with my wife (taking the photo), my mother, my son, and my brother.

033 Of course, every walk we go on ends up with me lugging my son around.


I wouldn’t trade it for anything. :), mvc, code 0 comments suggest edit

When we released ASP.NET MVC 2 Beta back in November, I addressed the issue of support for Visual Studio 2010 Beta 2.

Unfortunately, because Visual Studio 2010 Beta 2 and ASP.NET MVC 2 Beta share components which are currently not in sync, running ASP.NET MVC 2 Beta on VS10 Beta 2 is not supported.

The release candidate for ASP.NET MVC 2 does not change the situation, but I wasn’t as clear as I could have been about what the situation is exactly. In this post, I hope to clear up the confusion (and hopefully not add any more new confusion) and explain what is and isn’t supported and why that’s the case.


Part of the confusion may lie in the fact that ASP.NET MVC 2 consists of two components, the runtime and what we call “Tooling”. The runtime is simply the System.Web.Mvc.dll which contains the framework code which you would reference and deploy as part of your ASP.NET MVC application.

The Tooling consists of the installer, the project templates, and all the features in Visual Studio such as the Add View and Add Area dialogs. Much as ASP.NET 4 is different from Visual Studio 2010, the ASP.NET MVC 2 tooling is different from the runtime. The difference is that we primarily release both components in one package.

The reason I bring this up is to point out that when I said that ASP.NET MVC 2 RC is not supported on machines with Visual Studio 2010 Beta 2, I’m really referring to the tooling.

The ASP.NET MVC 2 RC runtime is fully supported with the ASP.NET 4 runtime. As I mentioned before, we are not compiling a different version of the runtime for ASP.NET 4. It’s the same runtime. So you can create an ASP.NET empty web application project, for example, add in the RC of System.Web.Mvc.dll as a reference, and go to town.

The problem of course is that you won’t have the full tooling experience at your disposal in VS2010 such as project templates and dialogs. This is definitely a pain point and very unfortunate.

Why don’t we ship updated installers for Visual Studio 2010 Beta 2?

This is a fair question. What it comes down to is that this would add a lot of extra work for our small team, and we’re already working hard to release the core features we have planned for this release.

Add this extra work and something would have to give. It would have to come at the cost of feature work and bug fixes and we felt those were a higher priority than temporary support for interim releases of VS2010.

Why would this add overhead? Eilon Lipton, lead developer on the ASP.NET MVC feature team, covers this well in his comment on my last post.

Regarding Visual Studio 2010 and .NET 4 support, that is unfortunately not a feasible option. The most recent public release of VS2010 and .NET 4 is Beta 2. However, our internal builds of MVC 2 for VS2010 and .NET 4 depend on features that were available only after Beta 2. In other words, if we released what we have right now for VS2010 and .NET 4 then it wouldn’t even run.

We are constantly syncing our internal builds with the latest builds of Visual Studio 2010. As Eilon points out, to support VS 10 Beta 2, we’d have to have two separate builds for VS10, one for Beta 2 and one for the latest internal build. Keep in mind, this is on top of the build for Visual Studio 2008 we’re doing.

Trying to sync our tooling against two different versions of Visual Studio is hard enough. Doing it against three makes it much more difficult.

As I mentioned before, the ASP.NET MVC 2 project schedule isn’t aligned with the Visual Studio 2010 schedule exactly. Heck, when ASP.NET MVC 1.0 was shipped, work on VS 10 was already underway, so we were playing catch-up to catch the VS 10 ship train. Thus when the Beta 2 was code complete, we weren’t done with our Beta. When we were done with Beta, we were already building our tools against a newer build of VS10. The same thing applies to the RC.

What about Visual Studio 2010 RC?

Funny thing is, since I’ve been on leave, I pretty much found out that we were even having a public Release Candidate for Visual Studio 2010 the same time you probably did via ScottGu’s Blog post on the subject.

The good news is that the Visual Studio 2010 Release Candidate will include a newer version of ASP.NET MVC 2. We’re still working out the details of which exact version we will include, though I’d really like it to be the RC of ASP.NET MVC, assuming the logistics and schedule line up properly.

And of course, the Visual Studio 2010 RTM will include the ASP.NET MVC 2 RTM and at that point, all will be well with the world as installing tooling for ASP.NET MVC 2 will be supported on both VS 2008 and VS 2010 at the same time.

So again, we do understand this is an unfortunate situation and apologize for the inconvenience this may cause some of you. Aftor all, I feel the same pain! I want to install both versions on my machine just like you do. Fortunately, it’s only a temporary situation and will all be a bad memory when VS2010 RTM is released to the world. Thanks for listening., mvc 0 comments suggest edit

Paternity leave is not all fun and games. Mostly it’s soothing an irate baby and toddler while dealing with explosive poo episodes. Believe me when I say the term “blow out” is apt. That’s probably not the imagery you were hoping for in a technical blog post, but I think you can handle it. ;)066 What!? It’s already time for an RC?! I think I need to be changed.

While I’m on leave, the ASP.NET MVC team continues its hard work and is now ready to announce the release candidate for ASP.NET MVC 2. Go get it now!

Download ASP.NET MVC 2 Release Candidate

As always, the release notes provide a summary of what’s changed. Also, stay tuned as I expect we’ll see one of those epic ScottGu blog posts on the release soon.


As you might expect from a release candidate, most of the work focused on bug fixes and improvements to existing features. We also spent a lot of time on performance profiling and optimization.

Much of the focus on this release was in the client validation scripts. For example, the validation script was moved into its own file and can be included at the top or bottom of the page. Client validation also now supports globalization.

The other change related to validation is that the ValidationSummary now supports overloads where only model-level errors are displayed. This is useful if you are displaying validation messages inline next to each form field. Previously, these messages would be duplicated in the validation summary. With these new changes, you can have the summary display an overall validation message (ex. “There were errors in your form submission”) as well as a list of validation messages which don’t apply to a specific field.

What’s Next?

RTM of course! The RTM release of ASP.NET MVC will be included in the RTM release of Visual Studio 2010, which is slated for some time in March. The VS2008 version of ASP.NET MVC 2 might release earlier than that. We’re still working out those details.

code 0 comments suggest edit

Many web applications (such as this blog) allow users to enter HTML as a comment. For security reasons, the set of allowed tags is tightly constrained by logic running on the server. Because of this, it’s helpful to provide a preview of what the comment will look like as the user is typing the comment.

sneak peek - by ArminH on
sxc.huThat’s exactly what my live preview jQuery plugin does.

See it in action

This is the first jQuery Plugin I’ve written, so I welcome feedback. I was in the process of converting a bunch of JavaScript code in Subtext to make use of jQuery, significantly reducing the amount of hand-written code in the project. Needless to say, it was a lot of fun. I decided to take our existing live preview code and completely rewrite it using JavaScript.

All you need for the HTML is an input, typically a TEXTAREA and an element to use as the preview, typically a DIV

<textarea class="source"></textarea>

<label>Preview Area</label>
<div class="preview"></div>

And the following script demonstrates one way to hook up the preview to the textarea.

$(function() {
        previewElement: $('div.preview'),
        allowedTags: ['p', 'strong', 'br', 'em', 'strike'],
        interval: 20

One thing that’s different between this implementation and others I’ve seen is you can specify a set of allowed tags. When typing in the textbox, the preview will render any tags in that list. If the user types in tags which are not in that list, the preview will HTML encode the tags.

Keep in mind that this plugin is for previewing what comments will look like and should not be used as validation! The preview might not exactly match your server-side logic.

Also for fun, I’m hosting the source code on GitHub as a way to force myself to learn what all the fuss is about GIT.

Thanks to Bohdan Zograf, this blog post is also available in Belarusian.

personal, code 0 comments suggest edit

Ok, it wasn’t necessarily my ass that was saved, but it was years worth of images which were important to me!

As I wrote yesterday, my blog’s hosting server had a hard-drive failure effectively wiping out my virtual machine, taking my blog down with it. Fortunately, I was able to get back up with a static archive of my site provided by Rich Skrenta, but I was missing all my images and other content (code samples).

As Jeff mentions,

I have learned the hard way that there are almost no organizations spidering and storing images on the web.

Keep in mind that the images are not just mere eye candy. In many cases, they serve to illustrate key concepts: “As you can see in the screenshot above, if the screenshot were still to exist, but through the sheer ineptitude of Phil you’ll have to guess at the knowledge it would have conveyed.

As I was lamenting the loss of these files, I started poking around my browser cache (finding this great tool for exporting the Google Chrome cache by the way which can retain directory structure) looking for stray images.

I then started thinking about alternative tools that might cache web content such as a client RSS reader, etc. Then it occurred to me, didn’t I run the IIS SEO Toolkit against my site recently (click to enlarge)?

SEO Toolkit
ScreenshotThe first time I saw the SEO Toolkit was when Carlos Aguilar gave me a demo a long while ago. Back then it was just something he put together over the weekend. As soon as I saw it I begged him (quite annoyingly I must say) to let me have a private build to try out. Eventually it was released and I was able to run it against to see how much I sucked.

Well it’s a good thing I ran it back in August! This tool stores a local cache of images. Oddly enough, it appends a .txt extension to every cached file.

cached-images No worries! Using a bit of DOS command magic, I was able to strip off the .txt extension from every file (note I ran this from the command line. If you put this in a batch file, you’ll need to double up on the % character).

for /r %x in (*.c) do ren “%x” “%~nx”

That stripped off the extensions. Afterwards I uploaded the images and am now only missing images for 18 blog posts, the posts written in August, September, and October of 2009. Those shouldn’t be too hard to recreate manually (though if you happen to have those images in your browser or RSS cache, I do appreciate you sending them to me! My email at Microsoft is philha)

Looks like I caught a lucky break this time in finding and leveraging the previously undocumented “Back up a website for dummies” feature in the IIS SEO Toolkit. Carlos, I owe you one! :)

UPDATE: If you were wondering why the cached files were stored with a .txt extension appended, Carlos revealed the mystery to me in an email.

Oh I forgot to explain that silly thing we do with file extensions is a “naïve-silly attempt” to reduce the accident of double-clicking a javascript, exe, or let the shell try to display ‘malign image’ that might come from external sites. Since in theory we consider that a ‘private’ cache we decided to do this silly trick to prevent any funky games with somebody generating an ‘brittney-spears-nude-picture.jpg.exe’ with the icon of a JPG file that lured someone into running it.

Agreed its pretty silly, but it was a simple ‘cheesy security feature’ easy to add for our ‘hidden cache’.

Basically it helps protect the double-click happy folks out there from hurting themselves accidentally.

personal 0 comments suggest edit

Yeah, the past few days have been a pretty low moment for me and this blog. Long story short, on December 11, a hard-drive failure took down the managed dedicated server which hosts my blog among other sites.

(The following image is a dramatization of actual events and is not the actual hard drive)

Hard-DriveThis is a server that Jeff Atwood and I share (we each host a Virtual Server on the machine), thus all of the following sites were brought down by the hardware malfunction:

That list doesn’t include my personal Subversion server (yes, I’m planning to switch to GitHub for that).

The good news is that my hosting provider, CrystalTech, was taking regular backups of the machine. The bad news is that all of these sites were hosted in virtual machines. The Virtual Hard Drive files (usually referred to as VHD files) which contain the actual data for our virtual machines were always in use and were not being backed up, silently failing each time.

Properly backing up a live virtual server requires taking advantage of Volume Shadow Copy Service (VSS) as described in this blog post to backup live virtual server VMs, but this was not in place, probably due to a lack of coordination between us and the hosting provider.


A data recovery company was brought in to try and recover the data. They replaced the drive head assembly and took a forensic image from the drive and started trying to recover our data. So far the actual VHD files we need have not yet been recovered. However, they were able to recover an older VHD I had backed up in 2007. That allowed me to grab all my content files such as images and code samples from back in 2007.

Luckily, I had recently backed up my database locally a few months ago. Not only that, thanks to the helpful Rich Skrenta, I was able to have a static web archive of my blog up and running quickly. He had a cache of both my and Jeff’s ( blog with the directory structure intact! That allowed me to retain my permalinks and have my content in a readonly state. I can only assume this cache is related to his search engine startup,

From there, I started using grepWin against a copy of those static HTML files to strip out the relevant information and convert the blog posts I didn’t have in my database into one big T-SQL script which would insert all the blog posts and comments back into my database.

I had to upgrade my blog to an unreleased version of Subtext because I was in the process of testing the latest version against the copy of my database. That’s why I copied it locally in the first place, so there might be potential wonkiness if I made any mistakes in the upgrade.

At this point, most of the content for my blog is back up. I’m missing some comments left on the most recent post and many of the images on posts after 2007. Unfortunately getting cached images en masse is a pretty big challenge.

I’m also missing some code samples etc, but I can start posting those back up there when I have time.

Lessons Learned

In general, I’m not a fan of the blame game as blame can’t change the past. It sucks, but what’s done is done. I’ll certainly let my hosting provider know what they can do better, but I also share in some of the blame for letting this happen.

What’s more interesting to me is learning from the past to help realize a better future, since that is something I can affect. What lessons did I learn (and re-learned because the lesson didn’t make it through my thick skull the first time) from this?

First and foremost as many mentioned to me on Twitter (thanks!):

An untested backup strategy is no backup strategy at all! Test your backups!

I think a corollary to that is to try and have a backup strategy that’s easy to setup. I actually had a process for backing up my database and content regularly, but when I moved to the new hosting provider, I forgot to set it up again.

I think the other lesson is that even if you have managed hosting, you should have your own local backups of the important content in your site.

Backup Strategy

I’m setting up a much better back-up strategy which will include automatic backup verifications by setting up my site on a local machine so I can browse the backup locally. When I get it in place, I’ll write a follow-up post and hope to get good suggestions on how to improve it.

UPDATE:Looks like I am having an issue with comments not showing up and over-aggressive spam controls. This is the result of dogfooding the latest trunk build of my software. ;) Glad to find these issues now before releasing the latest version. :)

UPDATE: 12/14/2009Jeff Atwood declares today to be International Backup Awareness Day and gives his perspective on the server failure that affected us both and how he sucks. Yes, I must share in that suck too.

UPDATE 12/14/2009 10:19 PMI was able to recover most of my images through a lucky break. I wrote about how the IIS SEO Toolkit saves the day.

Technorati Tags: hosting,backups,crystaltech,blog

aspnetmvc localization validation 0 comments suggest edit

This is the fourth post in my series on ASP.NET MVC 2 and its new features.

  1. ASP.NET MVC 2 Beta Released (Release Announcement)
  2. Html.RenderAction and Html.Action
  3. ASP.NET MVC 2 Custom Validation
  4. Localizing ASP.NET MVC Validation

In my recent post on custom validation with ASP.NET MVC 2, several people asked about how to localize validation messages. They didn’t want their error messages hard-coded as an attribute value.

world-in-handsIt turns out that it’s pretty easy to do this. Localizing error messages is not specific to ASP.NET MVC, but is a feature of Data Annotations and ASP.NET. And everything I cover here works for ASP.NET MVC 1.0 (except for the part about client validation which is new to ASP.NET MVC 2).

I covered this feature a back in March at Mix 09 in my ASP.NET MVC Ninjas on Fire Black Belt Tips talk. If you want to see me walk through it step by step, check out the video. If you prefer to read about it, continue on!

Let’s start with the ProductViewModel I used in the last post

public class ProductViewModel {
  [Price(MinPrice = 1.99)]
  public double Price { get; set; }

  public string Title { get; set; }

If we’re going to localize the error messages for the two properties, we need to add resources to our project. To do this, right click on your ASP.NET MVC project and select Properties. This should bring up the properties window. Click on the Resources tab. You’ll see a message that says,

This project does not contain a default resources file. Click here to create one.

Obey the message. After you click on the link, you’ll see the resource editor.

resources-tab Make sure to change the Access Modifier to Public(it defaults to Internal).


Now enter your resource strings in the resource file.


Hopefully my Spanish is not too bad. An ASP.NET build provider will create a new class named Resources behind the scenes with a property per resource string. In this case there’s a property named PriceIsNotRight and Required. You can see the new file in the Properties folder of your project.


The next step is to annotate the model so that it pulls the error messages from the resources.

public class ProductViewModel {
  [Required(ErrorMessageResourceType = typeof(Resources),
    ErrorMessageResourceName = "Required")]
  public string Title { get; set; }
  [Price(MinPrice = 3.99, ErrorMessageResourceType = typeof(Resources),
    ErrorMessageResourceName = "PriceIsNotRight")]
  public double Price { get; set; }

For the ErrorMessageResourceType, I just specify the type created by the build provider. In my case, the full type name is CustomValidationAttributeWeb.Properties.Resources.

For the ErrorMessageResourceName, I just use the name that I specified in the resource file. The name identifies which resource string to use.

Now when I submit invalid values, the error messages are pulled from the resource file and you can see they are in Spanish.

Client Validation - Windows Internet

Localized Error Messages Custom Client Validation

Note that these localized error messages continue to work even if you enable client validation. However, if you were to try it with the original code I posted in my last validation example, the error message would not work for the custom price validation attribute.

Turns out I had a bug in the code, which is now corrected in the blog post with a note describing the fix. Just scroll down to the PriceValidator class.

As always, I have a code sample you can look at. It’s the same example as before, just updated. Download the sample!

Tags: aspnetmvc,, validation, localization, data annotations