DRY in the MVC View

依然范特西╮ 提交于 2019-12-11 07:31:59

问题


I've been working a lot with asp.net web forms and one think that I like about the is the consistency with the generated markup e.g. if you create a composite control for a TextField you can control the generated markup in a single class like and don't break the SRP:

<form:textfield id="firstName" runat="server" required="true" label="First Name" />

I you're your going to generate the markup by hand it might look like this:

<label for="firstName" id="lbl_firstName">Name <span class="required">*</span></label>
<input id="firstName" name="firstName" type="text" value="" />

The problem is when would like to change something for example add a wrapping div or move the span. In worst case you have to edit thousands of views.

That's why I really like the MVC Contrib FluentHtml.

<%= this.TextBox(x => x.Message.PostedBy).Class("required").Label("Name") %>

My question is what do you think is the best way to add a wrapping div for the code line above? I think hand writing is not an option because of the arguments above? Perhaps extending the TextBox : MvcContrib.FluentHtml.Elements.TextInput?


回答1:


have you checked InputBuilder in MvcContrib project? it is used in Codecampserver as well. have a look and i think u will like it.




回答2:


Honestly, I don't think the example case you've given applies to real world. A textbox is a textbox. If you need one, you render one.
If you need a more "complex" control like a textbox wrapped in a div tag, then you can have a partial view for that.

For example, Model :

public class CustomControlModel {
    public string Name { get; set; }
    public string Value { get; set; }
    public string Class { get; set; }
    public bool WrapInDivTag { get; set; }
    //you get the idea
}

Custom Control :

<%@ Control Inherits="System.Web.Mvc.ViewUserControl<CustomControlModel>" %>
<%if (Model.WrapInDivTag) {%> <div> <% } %>
    <%=Html.TextBox(Model.Name, Model.Value, new { @class = Model.Class })%>
<%if (Model.WrapInDivTag) {%> </div> <% } %>

And when rendering :

<%Html.RenderPartial("CustomControl", 
    new CustomControlModel { Name = "name", WrapInDivTag = true }); %>

That's a very simple example but I hope it explains why I suggested partial views. Don't forget that you can expose another property to get which tag to render etc.




回答3:


InputBuilders are one option. With FluentHtml you could create a custom element, something like this:

public class TextBoxInContainer : TextInput<TextBox>
{
    public TextBoxInContainer (string name) : base(HtmlInputType.Text, name) { }

    public TextBoxInContainer (string name, MemberExpression forMember, IEnumerable<IBehaviorMarker> behaviors) : base(HtmlInputType.Text, name, forMember, behaviors) { }

    protected override ToString()
    {
         divBuilder = new TagBuilder(HtmlTag.Div);
         divBuilder.InnerHtml = ToString();
         return divBuilder.ToString(TagRenderMode.SelfClosing);
    }
}

To use this from your view you would extend IViewModelContainer something like this:

public static MyTextBox TextBoxInContainer <T>(this IViewModelContainer<T> view, Expression<Func<T, object>> expression) where T : class
{
    return new TextBoxInContainer (expression.GetNameFor(view), expression.GetMemberExpression(), view.Behaviors)
        .Value(expression.GetValueFrom(view.ViewModel));
}

Then if you want to change your container to a span sitewide, you change the ToString method of TextBoxInContainer.



来源:https://stackoverflow.com/questions/1617795/dry-in-the-mvc-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!