views:

125

answers:

2

Tried to create this Extension method. Works except that the helper is rendering text, not the control to the View when the page renders:

I included using System.Web.Mvc.Html; at the top of my helper class that contains this extension method so that it would understand helper.RadioButton.

public static string WriteTestControlToScreen(this HtmlHelper helper)
{
    StringBuilder fields = new StringBuilder();
    fields.Append("<fieldset>");
    fields.Append("     <div class='formLabel'><span class='requiredText'>*</span><label>Background Color</label></div>");
    fields.Append("     <div class='formField'>" + helper.RadioButton("rbBackgroundColorWhite", 0, false) + "<label class='fieldInlineLabel' for=''>White</label></div>");
    fields.Append("     <div class='formField'>" + helper.RadioButton("rbBackgroundColorWhite", 0) + "<label class='fieldInlineLabel' for=''>Black</label></div>");
    fields.Append("</fieldset>");

    return fields.ToString();
}

Output in the View then looks like this (notice it's not rendering a radiobutton but treating it as text instead):

*Background Color <%=Html.RadioButton('rbBackgroundColorWhite', 0, false)%>White <%=Html.RadioButton('rbBackgroundColorWhite', 0)%>Black

+1  A: 

I did a little poking around with Reflector, and I noticed that the MVC extension methods for Input fields all use an InputHelper class, which in turn uses a TagBuilder class:

private static string InputHelper(this HtmlHelper htmlHelper, InputType inputType, string name, object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, IDictionary<string, object> htmlAttributes)
{
 ModelState state;
 if (string.IsNullOrEmpty(name))
 {
  throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name");
 }
 TagBuilder builder = new TagBuilder("input");
 builder.MergeAttributes<string, object>(htmlAttributes);
 builder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType));
 builder.MergeAttribute("name", name, true);
 string str = Convert.ToString(value, CultureInfo.CurrentCulture);
 bool flag = false;
 switch (inputType)
 {
  case InputType.CheckBox:

              //...etc.

What follows are several case statements covering the additional rendering required for the various input types. But you get the point. The folks at MVC are not concatenating strings; they are using the MergeAttribute (and other) methods to do the dirty work for them. My guess is there is some browser compatibility goodness in there as well.

What I am suggesting is that you could use the TagBuilder class to build your HTML, just like the MVC folks do.

Robert Harvey
But in the end, aren't they just returning a string? i.e. return tagBuilder.ToString(TagRenderMode.SelfClosing);
Johnny G
Yes, but see my second answer below.
Robert Harvey
seems like I could reuse InputHelper and just pass in the input type and its attributes to get the same effect rather than re-invent the wheel and code a method for each type of control using TagBuilder
CoffeeAddict
sh**, InputHelper is private. I'd have to copy the same damn thing into my own class or something.
CoffeeAddict
Nothing wrong with that.
Robert Harvey
But you would have to pull in TagBuilder too, and anything else it depends on. The asp.net MVC source is available at http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471. I suppose you could make InputHelper public and recompile the DLL.
Robert Harvey
I'll just make my own controls. And thanks. Hey, tried to find InputHelper again in reflector, even tried to search. I had it up the other day. Is there any easy quick way to find this again. I looked at the assemblies and weird, I just don't see it.
CoffeeAddict
Nevermind, I cracked open the source and searched for it. It's under System.Web.MVC.Html then InputExtensions
CoffeeAddict
I agree, searching in Reflector is a bit hit or miss. It finds some things but not others. Good luck with the controls.
Robert Harvey
+1  A: 

The problem with your original code is that you are outputting <%= %> tags at a time when MVC is expecting literal html output. In other words, it's not processing these tags.

Consider putting your HTML in an .ASCX file and doing a RenderPartial.

Robert Harvey
but this is a helper method, are you saying put that in an .ascx? I don't always want to use an .ascx for all my HTML though.
CoffeeAddict
<%= %> expects source code right?
CoffeeAddict
"when MVC is expecting literal html output"...I'm not following sorry. Terminology issue for me.
CoffeeAddict
Is this: *Background Color <%=Html.RadioButton('rbBackgroundColorWhite', 0, false)%>White <%=Html.RadioButton('rbBackgroundColorWhite', 0)%>Blackin the browser or in VS2008?
Robert Harvey
got it, thanks!
CoffeeAddict
how did you know this? Just wondering how you figured that out or did you just assume that's the case based on the result?
CoffeeAddict
I opened the System.Net.MVC.dll using Reflector (http://www.red-gate.com/products/reflector/). Reflector can disassemble to c# code, so I disassembled the TextBox helper extension method, and followed the method calls to InputHelper and TagBuilder.
Robert Harvey
As far as your code is concerned, it looks like it should work, but the output suggests that it is trying to "bite its own teeth," so to speak.
Robert Harvey
>>>>Is this: *Background Color <%=Html.RadioButton('rbBackgroundColorWhite', 0, false)%>White <%=Html.RadioButton('rbBackgroundColorWhite', 0)%>Black in the browser or in VS2008?In the browser
CoffeeAddict
it works! good God: <%= Html vs. <%=Html
CoffeeAddict
Really? A space fixed it? I always put a space, but I didn't know it was required.
Robert Harvey