开发者

Aliased Form Names with HtmlHelpers

开发者 https://www.devze.com 2023-04-12 09:45 出处:网络
tl;dr How do I modify form element names that are generated to use aliased names that come from ModelMetadata.AdditionalValues instead? Preferably with a custom (or not custom) html helper.

tl;dr

How do I modify form element names that are generated to use aliased names that come from ModelMetadata.AdditionalValues instead? Preferably with a custom (or not custom) html helper.


I have a search view model with some custom object properties. Each property goes two more properties deep in my view. I also use editor templates in my view. My form ends up with elements like the following:

HTML

<input name="Field1.Field.Id" id="..." type="..." />
<input name="Field1.Field.Label" id="..." type="..." />
<input name="Field2.Field.Id" id="..." type="..." />
<input name="Field2.Field.Label" id="..." type="..." />

Search.spark (.aspx)

${ Html.EditorFor(m => m.Field1) } // Field1 is of type SearchField
${ Html.EditorFor(m => m.Field2) } // Field2 is of type SearchField
etc...

SearchField.spark (.ascx)

<viewdata model="SearchField" />
// *snip*
${ Html.EditorFor(m => m.Field) } // Field is of type SpecialField

SpecialField.spark (.ascx)

<viewdata model="SpecialField" />
${ Html.HiddenFor(m => m.Id) } // Id is of type int?
${ Html.TextBoxFor(m => m.Label } // Label 开发者_如何学JAVAis of type string

Because the form uses GET, I end up with very long query strings. What I'd like to do is provide aliases for the properties. I already have an attribute, a model metadata provider to populate AdditionalValues and a custom model binder to take care of the aliases, but I'm stuck on generating the proper html.

I thought I'd just write a custom html helper, but got stuck pretty fast.

public static MvcHtmlString HiddenForA<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
    var metadata =  ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);                

    if (metadata.AdditionalValues.ContainsKey("Alias"))
    {
        string alias = (string)metadata.AdditionalValues["Alias"];

        // what to do now?    
    }
}


You have the alias that you want to use, the value is available from metadata.Model then all you need to do is generate your HTML. You could use a tag builder, string.format or what ever you prefer, for the sake of readability I'll use string.format and have the properties in ' rather than ".

public static MvcHtmlString HiddenForA<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
    var metadata =  ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);                

    if (metadata.AdditionalValues.ContainsKey("Alias"))
    {
        string alias = (string)metadata.AdditionalValues["Alias"];
        string value = Convert.ToString(value, metadata.Model);

        string html = string.Format(@"<input type='hidden' name='{0}' value='{1}' >", alias, value);    
        return MvcHtmlString.Create(html);
    }
}

However, this will only handle the issue of your long URLs, this will mean that your model binding will not properly bind these on your action. To do this you'll need to either create a custom model binder or have your action take a viewmodel with properties of these names then either create a new object of your desired model and fill in its properties or use the viewmodel as is.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号