我已经搜索了这个问题,发现可能answer,但我仍需要一些帮助。
我正在尝试编写一个html-helper来扩展现有LabelFor方法的功能
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, IDictionary<string, object> htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
//string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
var labelText = html.LabelFor(expression);
if (String.IsNullOrEmpty(labelText.ToString()))
{
return MvcHtmlString.Empty;
}
if (metadata.IsRequired)
{
labelText = new MvcHtmlString(labelText.ToString().Substring(0, labelText.ToString().Length - 8).Trim() +
"<span style=\"color:red\" class=\"required-marker\">*</span></label>");
}
TagBuilder tag = new TagBuilder("label");
tag.MergeAttributes(htmlAttributes);
tag.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));
tag.SetInnerText(labelText.ToString());
return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
}
我正在尝试添加一个功能,其中Method将检查变量是否具有&#34; required&#34;标志,然后执行某些操作(在这种情况下在标签的末尾添加红色*)
[Required]
[Display(Name = "Year")]
public string ProjectYr { get; set; }
但是,我觉得我要覆盖整个LabelFor功能。有没有办法简单地向现有的LabelFor方法添加新功能,同时保留原始的所有功能而不覆盖它? 覆盖无论如何都不起作用,因为我的方法是静态的。
非常感谢您提前!
答案 0 :(得分:2)
这是一个完整的例子,可以满足您的要求
Accessing the model attributes in a helper extension class
public static class LabelExtensions
{
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression, IDictionary<String, Object> htmlAttributes,
String requiredMarker = "*")
{
return LabelHelper(html, ModelMetadata.FromLambdaExpression(expression, html.ViewData),
ExpressionHelper.GetExpressionText(expression), null, htmlAttributes, requiredMarker);
}
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression, Object htmlAttributes, String requiredMarker)
{
return LabelFor(html, expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), requiredMarker);
}
internal static MvcHtmlString LabelHelper(HtmlHelper html, ModelMetadata metadata, String htmlFieldName,
String labelText = null, IDictionary<String, Object> htmlAttributes = null, String requiredMarker = null)
{
var resolvedLabelText = labelText ??
metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
var tag = new TagBuilder("label");
tag.Attributes.Add("for",
TagBuilder.CreateSanitizedId(html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName)));
tag.SetInnerText(resolvedLabelText);
tag.MergeAttributes(htmlAttributes, true);
if (metadata.IsRequired && !String.IsNullOrWhiteSpace(requiredMarker))
{
var requiredSpan = new TagBuilder("span") {InnerHtml = requiredMarker};
requiredSpan.AddCssClass("required");
tag.InnerHtml += requiredSpan;
}
var result = tag.ToString(TagRenderMode.Normal);
return new MvcHtmlString(result);
}
}
这是单元测试
public static class LabelExtensionFixtures
{
[TestFixture]
public class should_return_label_with_required_info : MvcExtensionFixtureBase
{
private class TestClass
{
[Required]
public Guid Id { get; set; }
}
private MvcHtmlString _expectedResult;
private HtmlHelper<TestClass> _sut;
private MvcHtmlString _result;
[SetUp]
public void Given()
{
//arrange
_expectedResult =
MvcHtmlString.Create(
"<label class=\"control-label col-md-2\" for=\"Id\">Id<span class=\"required\">*</span></label>");
_sut = CreateHtmlHelper(new TestClass {Id = Guid.NewGuid()});
//act
_result = _sut.LabelFor(model => model.Id, new { @class = "control-label col-md-2" }, "*");
}
[Test]
public void Test()
{
//asert
Assert.That(_result.ToHtmlString(), Is.EqualTo(_expectedResult.ToHtmlString()));
}
}
}
public abstract class MvcExtensionFixtureBase
{
protected HtmlHelper<T> CreateHtmlHelper<T>(T instance)
{
var viewDataDictionary = new ViewDataDictionary<T>(instance);
var viewContext = A.Fake<ViewContext>();
A.CallTo(() => viewContext.ViewData).Returns(viewDataDictionary);
var viewDataContainer = A.Fake<IViewDataContainer>();
A.CallTo(() => viewDataContainer.ViewData).Returns(viewDataDictionary);
return new HtmlHelper<T>(viewContext, viewDataContainer);
}
}