Making HtmlHelper.TextBox Act Like it Should!
March 18th, 2008
I was working on my ASP.NET MVC demo and tried something new. I’ve been dying to be able to create form fields just like I can in Rails and MonoRail. So in Rails I can say:
<%= text_field :title %>
and in Monorail I can say (syntax may be a little rusty, forgive me, it’s been awhile):
<%= FormHelper.TextField("employee.FirstName") %>
and both will generate the similar code (given an employee named Joe):
<input type="text" name="employee.FirstName" id="employee_FirstName" value="Joe">
Notice that the framework automatically fills the value for employee.FirstName in the textbox. This is very nice for reusability because you no longer have to conditionally pass in the value of your textbox based on whether or not FirstName is null. Using either of these two frameworks I can now reuse the EXACT SAME form control for both Add & Edit. Beautiful.
Now imagine my dismay when I typed a similar command into the ASP.NET MVC Framework:
<%= Html.TextBox("employee.FirstName") %>
and got as output (paraphrasing):
<input type="text" name="employee.FirstName" id="employee_FirstName" value="">
Notice that now the value is not inferred. Wah! I realize they are still developing heavily on this framework, but I thought I’d add some code that will do this for me. Here is an extension method you can add to your classes that will give you this desired functionality. Please note that this is VERY basic, and currently does not accept attributes. I will add it as I see the need:
public static string TextBox(this HtmlHelper helper, string name, string nothing)
{
string[] object_and_method = name.Split('.');
if (object_and_method.Length == 2)
{
// Get the ViewData object from the current view
object data = helper.ViewContext.ViewData;
// Get the particular property in question
var properties = from
property
in
data.GetType().GetProperties()
where
property.Name.ToLower() == object_and_method[1].ToLower()
select property;
// Find the first property that was returned above
// (there will only be one property with a given name)
var p = properties.First();
// Get the value from the ViewData object for the given property
object value_object = p.GetValue(data, null);
// Default to empty string if null (for new objects)
string value = value_object == null ? string.Empty : value_object.ToString();
// Return the TextBox HTML
return TextInputBuilder.TextBox(name, value, 20, 0, null);
}
return helper.TextBox(name, "", 20, 0, ((IDictionary<string, object>)null));
}
As I mentioned, this is an extension method. The existing TextBox methods are also implemented as extension methods on a class called TextInputExtensions. This class has a method with the signature:
public string TextBox(this HtmlHelper helper, string htmlName)
Unfortunately, this keeps me from being able to define my own method with the same signature, therefore I added the second string parameter called “nothing”; otherwise ASP.NET throws an exception saying that my method & the afore mentioned method are ambiguous. If anyone knows a way around this, please let me know.
This was very quickly coded, so I’m sure it could be a lot better. I just wanted to show one way my desired functionality could be achieved. If you have any comments, please email them to me as my comments aren’t very stable at this point in time (joe at faithfulgeek dot org). I’d love to hear some thoughts around this!
- Posted 26 days ago
- comments[0]
- Permalink
- Digg This!
