When Internet Explorer was released, I downloaded it immediately and replaced my IE8. It works superbly except on a project that I was working on. For some reason, some javascripts are causing errors and won't work. I was using jQuery 1.4.x and jQuery UI 1.8.1.
After some investigation, the existence of the meta-tag to force IE compatibility and the outdated jQuery scripts were causing all the errors.
So I removed the meta-tag ("<meta http-equiv="x-ua-compatible" content="IE=8" />") and updated the jQuery reference to the latest greatest (1.5.1 and UI 1.8.11) - and all are happy again.
-- read more and comment ...
Tuesday, March 29, 2011
jQuery update for IE9
Monday, March 7, 2011
Munchkin Strategy: Wizard
Munchkin is a card game, where you play a character in battling monsters in order to get to the winning level (level 10 for regular or 20 for EPIC). The game involves some luck (drawing cards), strategies, a good amount of persuasion, trash-talking, and bantering back-and-forth with other players. That combination makes the game a lot of fun, interactive, and can be played again and again without getting boring.
For more information about Munchkin, you can read their website: http://www.worldofmunchkin.com/
If you are familiar with Dungeons & Dragons, then Munchkin should be somewhat familiar to you - a funny version of D&D. It has races & classes, curses, combat strength, charms, potions, etc.
The rest of this post assumes that you are somewhat familiar with the game, basic rules, and its vocabularies - outlining a basic strategy to use if you are playing as a Wizard class.
-- read more and comment ...
By
Johannes Setiabudi
@
9:30 PM
0
comments! add yours!
Wednesday, March 2, 2011
Integrating ELMAH into your ASP.NET MVC project
What is ELMAH? ELMAH stands for Error Logging Modules and Handlers. So it does what it says, logging errors. It's a plug-able stand alone module that you can integrate with your project quite easily.
From ELMAH's site:
Once ELMAH has been dropped into a running web application and configured appropriately, you get the following facilities without changing a single line of your code:
- Logging of nearly all unhandled exceptions.
- A web page to remotely view the entire log of recoded exceptions.
- A web page to remotely view the full details of any one logged exception.
- In many cases, you can review the original yellow screen of death that ASP.NET generated for a given exception, even with customErrors mode turned off.
- An e-mail notification of each error at the time it occurs.
- An RSS feed of the last 15 errors from the log.
1. Download ELMAH
You can get the compiled assemblies or the source files here: http://code.google.com/p/elmah/
2. Reference ELMAH's assemblies
If you get the compiled assemblies, just make a reference to Elmah.dll. If you get the source, you will need to build it and then reference it (either by project or by binary).
3. Modify web.config
Open your web.config and make these changes:
a. Add this "configSections" within "configuration"
<configSections> <sectionGroup name="elmah"> <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah"/> <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah"/> <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah"/> <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah"/> </sectionGroup> </configSections>b. Add this "elmah" section within "configuration" under the "configSections". This will enable ELMAH to save the error log to the database using "MyAppConnectionString" connection string. If you want to save the log into XML files on a local disk, you can uncomment the second line (and comment the 4th line) and specify the saving location under "logPath".
<elmah> <!--<errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="~/App_Data"/>--> <security allowRemoteAccess="1"/> <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="MyAppConnectionString"/> </elmah>c. Within "system.web" section, add these lines:
<httpHandlers> <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah"/> </httpHandlers> <httpModules> <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/> </httpModules>d. Within "configuration", configure the permission to see the log. Basically it will deny all users unless users are logged in and user name is listed in the "allow" list. Enable that by adding these lines:
<location path="elmah.axd"> <system.web> <authorization> <allow users="admin,joe,bob"/> <deny users="*"/> </authorization> </system.web> </location>
4. Modify global.asax
Check in your global.asax whether this line exists:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");If it is, then no more changes are needed in the global.asax.
5. Preparing Database
If you elect to store the log in the database, then some tables and stored procedures must be created before ELMAH can be functional. Get the script to create all those tables & stored procedures here: http://code.google.com/p/elmah/wiki/Downloads?tm=2 and run it.
That should be it and ELMAH is ready to run - you can start accessing ELMAH under /elmah.axd from your root url.
But I went a step further - I want all exception, including handled one to also be captured in ELMAH. ASP.NET MVC provides an filter-attribute called "HandleError" to handle/catch all errors/exceptions happening in the controller or bubble all the way to the controller. So instead of using that, I made my own HandleError attribute that will log to ELMAH - and replace the stock [HandleError] with my [ELMAHHandleError] attribute.
6. Create [ELMAHHandleError] for all my controllers.
I took this code from NerdDinner example that ASP.NET team provides in CodePlex.
public class ELMAHHandleErrorAttribute : HandleErrorAttribute { public override void OnException(ExceptionContext context) { base.OnException(context); var e = context.Exception; if (!context.ExceptionHandled // if unhandled, will be logged anyhow || RaiseErrorSignal(e) // prefer signaling, if possible || IsFiltered(context)) // filtered? return; LogException(e); } private static bool RaiseErrorSignal(Exception e) { var context = HttpContext.Current; if (context == null) return false; var signal = ErrorSignal.FromContext(context); if (signal == null) return false; signal.Raise(e, context); return true; } private static bool IsFiltered(ExceptionContext context) { var config = context.HttpContext.GetSection("elmah/errorFilter") as ErrorFilterConfiguration; if (config == null) return false; var testContext = new ErrorFilterModule.AssertionHelperContext(context.Exception, HttpContext.Current); return config.Assertion.Test(testContext); } private static void LogException(Exception e) { var context = HttpContext.Current; ErrorLog.GetDefault(context).Log(new Error(e, context)); } }
That's it!
For further reading:
- Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components
- DotNetSlackersArticle in configuring ELMAH
-- read more and comment ...
By
Johannes Setiabudi
@
9:51 PM
2
comments! add yours!
Thursday, February 17, 2011
Mowbol Weekly: Using Corona
Mowbol.com (AWH's sister company), a company that focuses on mobile development recently did a series of videos about mobile platform. The last one was particularly interesting as it discussed using Corona to build a code once publish for both Android & iOS.
Chris Slee talks about Corona and the new Mowbol channel framework from mowbol.com.
So if you need to get into the app store fast on Android phones and tablets, iPhones, iPads, we need to talk.
You can go to mowbol's website here: http://www.mowbol.com
Mowbol also has a Youtube channel under mowboldotcom: http://www.youtube.com/user/mowboldotcom
-- read more and comment ...
By
Johannes Setiabudi
@
11:11 AM
0
comments! add yours!
Tuesday, February 8, 2011
Performance Tips (LINQ to SQL)
One part of the application that I am working on is performing poorly. According to the performance measurement that I get from using EQATEC profiler, it takes 3-4 seconds to load this page.
IIS / UI
Since this is a web application, so I made sure all the IIS/non-application performance enhancements are in place:
- IIS compression are turned on
- Javascript files are combined and compressed
- CSS files are combined and compressed
- Images, scripts, and CSS files are cached
- Conforming to YUI rules & Google PageSpeed performance rules
-- read more and comment ...
By
Johannes Setiabudi
@
10:09 PM
0
comments! add yours!
Monday, January 31, 2011
Using Except() Method in LINQ
There is a method that I rarely use in LINQ called "Except" - but it comes handy in my latest coding. So I thought I'd share how I use it. This method is for an IEnumerable and has multiple signatures: one that takes a second IEnumerable to exclude and the other one takes an IEnumerable and a comparer. You can read the spec in full here.
Here is an example:
int[] oneToTen = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int[] oneToTenEven = { 2, 4, 6, 8, 10 }; int[] oneToTenOdd; // do some exclusion here oneToTenOdd = oneToTen.Except(oneToTenEven); // so that oneToTenOdd will have { 1, 3, 5, 7, 9 };
Imagine this hypothetical situation where you are at a dealership and want to separate the cars that have been washed and ones that have not. Cars may have the same make, model, color, type, but each has different VIN number.
IEnumerable<Car> allCars = GetAllCars(); IEnumerable<Car> carAlreadyWashed = GetCarAlreadyWashed(); IEnumerable<Car> carNotWashed; // do some exclusion here carNotWashed = allCars.Except(carAlreadyWashed);The above code which will normally work for simple comparison, won't work because the run-time will have no idea that it has to compare based on VIN number. We have to tell it to use that field to do comparison.
public class CarComparer : IEqualityComparer<Car> { public bool Equals(Car x, Car y) { //Check whether the compared objects reference the same data. if (Object.ReferenceEquals(x, y)) return true; //Check whether any of the compared objects is null. if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false; //Check whether the Car' properties are equal. return x.VIN == y.VIN; } // If Equals() returns true for a pair of objects // then GetHashCode() must return the same value for these objects. public int GetHashCode(Car car) { //Check whether the object is null if (Object.ReferenceEquals(plan, null)) return 0; //Get hash code for the VIN field. int hashCarVIN = car.VIN.GetHashCode(); return hashCarVIN; } }Now then we can modify our code to be such as this:
IEnumerable<Car> allCars = GetAllCars(); IEnumerable<Car> carAlreadyWashed = GetCarAlreadyWashed(); IEnumerable<Car> carNotWashed; // do some exclusion here carNotWashed = allCars.Except(carAlreadyWashed, new CarComparer());
By
Johannes Setiabudi
@
4:45 PM
2
comments! add yours!
Friday, January 7, 2011
Microsoft Certification exams
My employer (AWH - http://www.awh.net) encourages us (the employees) to take MS certifications. Not only this will benefit the company in maintaining our status as a Gold Partner, but also will benefit us as far as knowledge, new technology, etc. Plus the certifications are attached to the individual, so if you change jobs, those certifications certainly belong in your resume and can be leveraging points.
AWH will pay for the tests, including first failure. So if I take a test and fail, and then retake the test and pass, AWH will cover both exams. So I have to pass before the reimbursement can come through.
Anyway, so last November, I saw a promotion on Prometric's website for a 2/3/4/5 exam packets with discounted price and FREE retakes for each exams in the packet. With that good deal in mind, I decided that I will set a goal in this area: getting a MCPD - Microsoft Certified Professional Developer. This certification requires 4 exams:
I took the first test early in December and passed it quite easily. Since ASP.NET is what I use daily, most of the questions in the test are familiar to me and I can answer them correctly.
I scheduled to take the ADO.NET test on Dec 23rd, but when I came to the facility, it was closed. I was not notified of any closing and Prometric also was not aware of the closing of the local facility (New Horizons). Prometric was able to reschedule me for Dec 27th at a different facility. I failed my ADO.NET test - probably by 2 or 3 questions, it was so close. Although I use ADO.NET stuff pretty much daily, but there are some things in there that are pretty new to me and I have not used them in production quality code - like Entity Framework. Those questions stumped me and resulting in a failing grade. Thank God for the free retake!
So I studied more EF, practice making some projects with with etc and retake the test on December 29th. I passed.
So next up is WCF - scheduled for Jan 12th. Hopefully by end of Feb 2011, I will have become an MCPD.
-- read more and comment ...
By
Johannes Setiabudi
@
12:34 PM
0
comments! add yours!
Tuesday, December 28, 2010
T-Mobile Customer Experience
One of my personal conviction is generosity. So that conviction, combined with good service (especially paid ones) usually produce a desire to reward the service giver beyond the typical means. I personally don't think this is unique to me - for example in tipping your servers in a restaurant, when you are getting excellent service, some people will give more tip, etc.
In this particular experience, I was getting superb service from T-Mobile and this blog post is a way of rewarding them of their excellent efforts to me as a customer.
-- read more and comment ...
By
Johannes Setiabudi
@
11:07 AM
3
comments! add yours!
Tuesday, November 23, 2010
Windows Phone 7 Experience

So for my new phone, I bought an HTC HD7, running the new Windows Phone 7. This blog post is about my experience with it so far - what I like about it, dislike, a little bit comparison to Android, etc. Nothing really scientific, but just sharing my experience, including an app development experience (since I am a software engineer). Obviously, my experience is a combined experience between the hardware (HTC HD7), the OS (WP7) - but when necessary I will mention the specifics.
What I REALLY Like
- This is something that is hard to describe, but there is such a pleasant feeling in using the device with the WP7. Every scroll is buttery smooth, no lag, no stutter, snappy, and my user-experience for the 80% of my usage of the phone is superb (this includes making phone calls, receiving calls, speaker phone, contacts, searches, calendar, email syncs, twitter, browsing).
- Panoramic view is totally awesome. It helps to go through things quickly, less click/swipe/back, etc. The panoramic background in some hubs are also contributing to increase the niceness and pleasant of using the device. All this being carried in a 4.3" screen - superb. iPhone 4 screen is better with the Retine Display, but HTC HD7's is bigger.
- The lock screen is also surprisingly well designed. I did not think about this before - but then I realized that showing all my notifications & next event on the lock screen is awesome! One of my cell-phone related habit is to look at my phone to see the time AND to see what is the next item in my calendar - which totally fits into the WP7 paradigm (and I have a feeling that I am not the only one with that habit).
- The email interface is awesome, every email is delineated well, clear text, eye-pleasing font, easy to use (virtual) keyboard, the sync is also fast, and does not lock the screen, excellent progress bar with the dots, etc. As far as email related experience, this is probably the best I have seen (compared to iPhone/iPod Touch, WinMo, BB, Android).
- The Calendar interface is also very robust and well done. It syncs seamless with my Exchange calendar, displays the next "event" on "Home" and "lock" screens, and for the extra kick, the calendar date "flips" when you scroll the events in the event list. Haha - I thought that was small but slick nonetheless.
- The "Tile" or the "Metro" design. I though it is awesomely done and intuitive. I am a bit biased to big icons - so the tile suits me well. Some also animate (changes in photos, people, news images, etc) - which added some "wow" factor to it. Some provide crucial information: the weather app gives the current weather summary, Outlook shows number of new messages, etc. There is no extra "widget" or differentiation between "widget" and "app shortcut" (like in Android) - which makes things simpler.
- The Media hub is really nice, it combines radio (like iHeartRadio), YouTube streams, your videos, music, podcasts, etc, and organized well via panoramic views. They just works seamlessly. No need to open YouTube app separately or media player app or radio app separately. One hub and everything works.
- Zune software. I HATE itunes - and Zune is awesome. Much better design, fast, unobtrusive updates, AND YOU CAN SYNC WITH MULTIPLE COMPUTERS! Yeay! Also, sync media over the air!
- Developing an app for WP7 is very very easy. Well I am a bit biased since I use Microsoft tools for my work. But here is the thing - I experienced quite some pain to get Android/iPhone dev environment to be up and running and I did created a some kind of "hello world" app, but nothing beyond that. With WP7, in 2+ hours I cranked out a panoramic RSS reader with style and all. Certainly (subjectively) a huge added value for me.
- XBOX Live is really cool. You can create/modify your Avatar from the phone, play some games, sync accomplishments, etc. But, since I am not a big XBOX Live player, I don't use this feature as much.
- Instead of paying per music/album, Zune allows you to pay subscription based: A $14.99 / mo gives you unlimited access to millions of songs you can stream on your PC, Xbox 360, Windows Phone 7, or Zune HD - AND you get to keep 10 per month FOR FREE FOREVER!
- The WP7 OS is always stock and all the bloatware from carriers can always be uninstalled just like any other app without rooting or hack. This was not my experience with Android or WinMo.
- WP7 Bing's voice search/command seems to be able to pick up my voice better compared to my old Android. I don't think this is a big deal - could be just because my G1 can't go beyond Android 1.6. I think Froyo most likely has better support for this.
- The robust kick-stand in HTC HD7. It's awesome when watching videos or reading on a table.
- The camera is nice. Being able to take 720p video and take a 5mpix photos are good features to have. Plus, the camera software is really fast - you can go from "lock" to "save picture" in about 5 seconds or less. Although I consider this as "not as important" for now, but I do see that I take pictures more because of the quickness or the camera & its ease of use.
- Marketplace. It needs to differentiate the search between music, apps, games, etc. Right now, when I am searching for "News", it gives me ALL related with "news" instead of contextual search result. I am fine with the "all" search and there are times when it is useful, but there needs to be specific search filter too.
- Map & navigation. Bing maps in WP7 is awesome and slick, but Android's turn by turn saved my ass multiple times. I heard some rumors that this is coming out in SP1 in Q1 2011 - at least I hope so.
- Need more apps, FREE apps. I want my free "Alchemy" or "Angry Bird" like in Android ... Or QR code reader, Google Sky Map. More apps ... WP7 apps availability is nothing compared to iPhone or Android.
- Twitter integration to People, like Facebook or MySpace or LinkedIn
- Phone wide search. Search people, docs, emails, etc from a single place.
- Windows Phone 7 - for those of you who are skeptical, I suggest you to try it. I was too a skeptics, but I am sold out now. Yes, it is not perfect, has room for improvement, but it is my device of choice for now.
- Android, probably the G2 - fast with HSPA+, excellent keyboard, stock Froyo, loaded with free apps, nice slick phone. (Or if you are on Verizon, go with Droid X)
- iPhone - only if iPhone is available outside AT&T.
-- read more and comment ...
By
Johannes Setiabudi
@
9:51 PM
0
comments! add yours!
Monday, November 22, 2010
Acadia National Park
But the highlight of our trip was when we were at Acadia National Park in Maine. Acadia National Park is about 5 hours north of Boston, MA. When I planned our trip, I had some expectations about how beautiful this park going to be, but I was still blown away - it exceeded all of my expectations! I think all of our family and friends agreed that it was the best national park we've seen and the highlight of our trip. I eager to go back next year and spend more time over there.
Acadia National Park has everything - like from beaches (ocean sandy beach or lake beach), serene lakes, hiking trails, bike trails, rocky coastline, sandy coastline, mountains, and spectacular mountain top view.
Anyway - if you have the time, Acadia is a must visit. I think our family is going back there in summer 2011!

-- read more and comment ...
Tuesday, October 26, 2010
Smart Power Control
I setup an SSH server at home running on my Media Center box. ALL of the shows that I am recording runs at night, so during the day, other than the time it has to download updates or running some batch process, it usually goes to suspend/sleep mode - which of course makes my SSH to become unavailable.
Why not just turn on "Wake up on LAN"? Well, I tried that and it worked, but it also somehow wake up the PC when I don't want it - like in the middle of the night or on a Saturday morning, or several seconds after it goes to sleep. In the end, I basically turn-off "Wake up on LAN" and trying to find a different solution.
Basically, what I want is this:
- The PC needs to be on between 8am to 5:30pm - this the window where I usually need my SSH
- It also needs to be recording my scheduled recording in Media Center
- Other than those, it should be in suspend/sleep mode
So for a while I just put my PC to "Never" sleep and just turn it off at night and turn it back on in the morning. I moved all my scheduled maintenance stuff (virus scan, windows update, etc) to morning/afternoon. Obviously this gets to be a pain after a while - especially when I keep forgetting to turn it on or off.
So for now, I use a software called "SmartPower" - where I schedule my PC to be "ON" between certain times and/or when certain parameters are set. Here is an article in LifeHacker about it. The way to use it is basically setting your computer to "Never" sleeps, and let SmartPower take over the sleep management (instead of letting Windows doing it). So, to meet my needs, I set:
- In "Schedules" tab to awake / stay on during the weekdays between 8:15am to 11:55pm
- Under "CPU" tab, set to 27% - this is for watching recordings past midnight or on weekends
- I set my PC to awake when Media Center remote is used
Additional readings:
-- read more and comment ...
By
Johannes Setiabudi
@
1:49 PM
0
comments! add yours!
Thursday, October 7, 2010
Conditional Reference in VS 2010
In one of our projects, we are using some third party components that have separate dlls for 32 bit and 64 bit. Since our old development box and production server were 32 bit, so we used the 32 bit version. No problem whatsoever.
In a different project for different client, our development box is a 64 bit machine. But, since we are running VS 2010 and using Cassini for our debugging, we use the 32 bit reference. But since our production box is running 64 bit, last minute before build for release in our build server, we swap the reference to 64 bit, re-check-in and build. So we just keep doing it that way - until one day, we forgot to do that and a production build got pushed to production environment and (of course) it breaks. So we fix it and then we vowed to find a solution to the last minute reference swap thing.
In VS, right click on the project that has the reference to the 32/64bit ref, do an unload project and open using XML editor and in it, you will see something like this:
... <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> </PropertyGroup> ... <ItemGroup> <Reference Include="Project.Reference.MyProject"> <HintPath>..\References"Project.Reference.MyProject.40.x86.dll</HintPath> </Reference> </ItemGroup> ...What you need to do is add a condition in your project file, so on certain environment it will use the x86 and x64 for other. The easiest way to do this (which is what we did) is adding a conditional statement itself on the reference element - when compiled as "debug", use the x86 dll and to use the x64 when compiled as "release". So we changed it to be like this:
... <ItemGroup> <Reference Include="Project.Reference.MyProject" Condition="'$(Configuration)' == 'Debug'"> <HintPath>..\References\"Project.Reference.MyProject.40.x86.dll</HintPath> </Reference> </ItemGroup> <ItemGroup> <Reference Include="Project.Reference.MyProject" Condition="'$(Configuration)' == 'Release'"> <HintPath>..\References\"Project.Reference.MyProject.40.x64.dll</HintPath> </Reference> </ItemGroup> ...
By
Johannes Setiabudi
@
4:45 PM
1 comments! add yours!
Tuesday, September 14, 2010
Session Timeout Settings in IIS7
We did a release to a production environment running IIS7.x, .NET 4, MVC2, etc. Everything went smoothly and after several hours, we started to get calls about time-out issue. Our users want the time-out to be 1 hour (the current setting) which is obviously longer than 20 minutes (which is the default setting).
I remember changing and rechecking this parameter value in the web.config and also in the IIS box, both in our test and production environments. So we double checked and everything was setup correctly - so we did our own test. After 10 minutes, no time out - as expected. But on the 20-25 minutes test, we did get a time out. We triple-check our web.config and application pool setting - they are all setup correctly.
- Application Pool -
- Advanced Settings Menu - Process Model - Idle Time-out (minutes) - Sites -
- Session State - Cookie Settings - Time-out (in minutes) - If you are using State Server or SQL Server to manage your session (instead of InProcess), you will need to set these values up too: Sites -
- Session State - Session State Mode Settings - Under web.config - system.web - authentication mode - forms - timeout (for form authentication)
By
Johannes Setiabudi
@
10:28 AM
1 comments! add yours!
Thursday, August 26, 2010
VS 2008 locking up after Office 2010 install
I installed MS Office 2010 about 3 weeks ago and everything went smooth. For the most part, I have been developing in VS 2010, but lately, when I was doing code review, I have to a .NET 3.5 project in VS 2008 - and it locks up on me almost every time.
I thought it was some extension I installed or something screwed up on my project. So I uninstall all extensions, but it was still locking up. I open the project on a different computer, it was running fine, same source and references and all that.
I went to search on the internet and found out that there are some issues between VS 2008 and Office 2010 installation. One my particular issue, all I need to do is to rerun "Microsoft Visual Studio Web Authoring Component".
The setup.exe file is located at : C:\Program Files (x86)\Common Files\microsoft shared\OFFICE12\Office Setup Controller\.
So just shut down all VS 2008 instance and any Office programs and then run the Setup.exe and it should be good to go - at least that did it for me.
Credit to Martin Hinshelwood!
-- read more and comment ...
By
Johannes Setiabudi
@
9:56 AM
0
comments! add yours!
Wednesday, August 25, 2010
StringLength validator into MaxLength attribute via Html Helpers
Let's say you use Data Annotation validations and attributes in your object classes, such as this:
[StringLength(50, ErrorMessage = "Title may not be longer than 50 characters")] public string Title { get; set; } [DisplayName("First Name")] [Required(ErrorMessage = "First Name is required")] [StringLength(100, ErrorMessage = "First Name may not be longer than 100 characters")] public string First { get; set; } [DisplayName("Last Name")] [Required(ErrorMessage = "Last Name is required")] [StringLength(100, ErrorMessage = "Last Name may not be longer than 100 characters")] public string Last { get; set; }
Then you setup your view:
<table> <tr> <td class="fieldLabel"><%:Html.SmartLabelFor(m => m.Title)%></td> <td class="fieldValue"><%:Html.EditorFor(m => m.Title)%> <%:Html.ValidationMessageFor(m => m.Title)%></td> </tr> <tr> <td class="fieldLabel"><%:Html.SmartLabelFor(m => m.Last)%></td> <td class="fieldValue"><%:Html.EditorFor(m => m.Last)%> <%:Html.ValidationMessageFor(m => m.Last)%></td> </tr> <tr> <td class="fieldLabel"><%:Html.SmartLabelFor(m => m.First)%></td> <td class="fieldValue"><%:Html.EditorFor(m => m.First)%> <%:Html.ValidationMessageFor(m => m.First)%></td> </tr> </table>Everything works great, the validators are validating, the display name shows up correctly, etc. Then you realize that it would have been much more awesome if the textbox is also limiting the entry to the StringLength specs using the maxlength attribute of the input element. It should not be that bad, right? Pretty easy? Just make or modify an Html helper and display another attribute based on a validation value - right? Nope ... turns out it is quite a challenge.
The ModelMetadata has all the validators, so we can get them. Once we get all the validators, it's only a matter of getting the one we want, which is the one associated with StringLength, then it's all a matter of appending the right Html attribute the the element. Here is the completed code (named string.ascx, located in /Views/Shared/EditorTemplates/):
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %> <% System.Collections.Generic.Dictionary<string, object> attributes = new Dictionary<string, object>() { { "class", "text-box single-line" } }; IEnumerable<ModelValidator> validators = ModelValidatorProviders.Providers.GetValidators(ViewData.ModelMetadata, ViewContext); ModelClientValidationRule stringLengthRule = validators.SelectMany(v => v.GetClientValidationRules()).FirstOrDefault(m => m.ValidationType == "stringLength"); if (stringLengthRule != null && stringLengthRule.ValidationParameters.ContainsKey("maximumLength")) { attributes.Add("maxlength", stringLengthRule.ValidationParameters["maximumLength"]); } Response.Write(Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, attributes)); %>Additional readings:
By
Johannes Setiabudi
@
10:08 PM
4
comments! add yours!