I am building a project with a lot of common code regarding the razor view.
Example:
<div class="form-group">
@Html.LabelFor(model => model.LayoutFrontAmount, htmlAttributes: new { @class = "control-label col-xs-12 col-sm-4 col-md-3" })
<div class="col-xs-4 col-sm-2 col-md-2 col-lg-1">
@Html.EditorFor(model => model.LayoutFrontAmount, new { htmlAttributes = new { @class = "form-control" } })
</div>
<div class="col-xs-12 col-md-8 col-sm-offset-4 col-md-offset-3">
<span class="help-block">@Html.ValidationMessageFor(model => model.LayoutFrontAmount, "", new { @class = "text-danger" })</span>
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LayoutFrontBackAmount, htmlAttributes: new { @class = "control-label col-xs-12 col-sm-4 col-md-3" })
<div class="col-xs-4 col-sm-2 col-md-2 col-lg-1">
@Html.EditorFor(model => model.LayoutFrontBackAmount, new { htmlAttributes = new { @class = "form-control" } })
</div>
<div class="col-xs-12 col-md-8 col-sm-offset-4 col-md-offset-3">
<span class="help-block">@Html.ValidationMessageFor(model => model.LayoutFrontBackAmount, "", new { @class = "text-danger" })</span>
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LayoutTRC, htmlAttributes: new { @class = "control-label col-xs-12 col-sm-4 col-md-3" })
<div class="col-xs-4 col-sm-2 col-md-2 col-lg-1">
@Html.EditorFor(model => model.LayoutTRC, new { htmlAttributes = new { @class = "form-control" } })
</div>
<div class="col-xs-12 col-md-8 col-sm-offset-4 col-md-offset-3">
<span class="help-block">@Html.ValidationMessageFor(model => model.LayoutTRC, "", new { @class = "text-danger" })</span>
</div>
</div>
The only thing that changes is the Model's property.
Is there a way to replace all the code with something like:
@TemplateName1(model => model.LayoutFrontAmount)
@TemplateName1(model => model.LayoutFrontBackAmount)
@TemplateName1(model => model.LayoutTRC)
You can create a HtmlHelper extension method that will generate all the html for a property, including the label and input element
using System;
using System.Linq.Expressions;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace YourAssembly.Html
{
public static class BootstrapHelper
{
public static MvcHtmlString BootstrapEditorFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
{
MvcHtmlString label = LabelExtensions.LabelFor(helper, expression, new { @class = "control-label col-xs-12 col-sm-4 col-md-3" });
MvcHtmlString editor = EditorExtensions.EditorFor(helper, expression, new { htmlAttributes = new { @class = "form-control" } });
MvcHtmlString validation = ValidationExtensions.ValidationMessageFor(helper, expression, null, new { @class = "text-danger" });
// Build the input elements
TagBuilder editorDiv = new TagBuilder("div");
editorDiv.AddCssClass("col-xs-4 col-sm-2 col-md-2 col-lg-1");
editorDiv.InnerHtml = editor.ToString();
// Build the validation message elements
TagBuilder validationSpan = new TagBuilder("span");
validationSpan.AddCssClass("help-block");
validationSpan.InnerHtml = validation.ToString();
TagBuilder validationDiv = new TagBuilder("div");
validationDiv.AddCssClass("col-xs-12 col-md-8 col-sm-offset-4 col-md-offset-3");
validationDiv.InnerHtml = validationSpan.ToString();
// Combine all elements
StringBuilder html = new StringBuilder();
html.Append(label.ToString());
html.Append(editorDiv.ToString());
html.Append(validationDiv.ToString());
// Build the outer div
TagBuilder outerDiv = new TagBuilder("div");
outerDiv.AddCssClass("form-group");
outerDiv.InnerHtml = html.ToString();
return MvcHtmlString.Create(outerDiv.ToString());
}
}
}
Then you can register this in your web.config
file (means you do not need @using ...
in the view
<namespaces>
<add namespace="System.Web.Mvc" />
....
<add namespace="yourAssembly.Html " /> // add this
</namespaces>
Now in your main view your can generate all the html shown in your question with just the following 3 lines of code
@Html.BootstrapEditorFor(m => m.LayoutFrontAmount)
@Html.BootstrapEditorFor(m => m.LayoutFrontBackAmount)
@Html.BootstrapEditorFor(m => m.LayoutTRC)
And if you want this to be reusable across multiple projects, compile it in separate dll and add a reference to it in your projects.
Depends on what the types are for each of LayoutFrontAmount, LayoutFrontBackAmount, and LayoutTRC. Are these all strings? If so, you could have a common view file that stores the template for displaying each, and then display each of them by using @Html.Partial()
in your primary view:
MyView.cshtml
@model string
<div class="form-group">
@Html.LabelFor(model => Model, htmlAttributes: new { @class = "control-label col-xs-12 col-sm-4 col-md-3" })
<div class="col-xs-4 col-sm-2 col-md-2 col-lg-1">
@Html.EditorFor(model => Model, new { htmlAttributes = new { @class = "form-control" } })
</div>
<div class="col-xs-12 col-md-8 col-sm-offset-4 col-md-offset-3">
<span class="help-block">@Html.ValidationMessageFor(model => Model, "", new { @class = "text-danger" })</span>
</div>
</div>
And then in your main view file you could render each of LayoutFrontAmount, LayoutFrontBackAmount, and LayoutTRC as follows:
@Html.Partial("MyView", Model.LayoutFrontAmount);
@Html.Partial("MyView", Model.LayoutFrontBackAmount);
@Html.Partial("MyView", Model.LayoutTRC);
If they are different types, that poses a bigger challenge.