以编程方式确定要在页面上输出的 html 元素类型 - 此逻辑应位于何处
本文关键字:类型 元素 于何处 html 方式确 编程 输出 | 更新日期: 2023-09-27 18:32:11
我有一个下拉列表,表示与文档相关的各种"属性"字段。例如,文档可以具有"标签"字段,该字段需要一个文本框才能在其中输入标签。或者它可能有一个位置字段,这将具有用户可以选择的各种位置类型的预填充下拉列表。或者它可能是一个截止日期字段,我们有一个自定义日期选择器的东西,我们用于选择日期。
我的问题:我想在我的控制器操作中声明一个 HtmlHelper,该操作在选择适当的属性字段时触发。我会针对 Attribute.Type 进行切换,并根据类型,我会在我的视图模型中返回要在视图中呈现的适当 html。如果我这样做,我可以对我的 switch 语句进行单元测试。
我读到了很多,在控制器中声明 HtmlHelper 是一个坏主意。我能理解这种情绪——有没有更好的方法可以做到这一点?我想尽可能避免逻辑,因为我根本无法对其进行单元测试。
我看到的另一种方法是在视图模型中传递 Attribute.Type,并在视图上执行切换逻辑以确定要调用哪个 HtmlHelper 方法。这是要走的路吗?提前谢谢。
编辑:我说的是想在代码隐藏中做这样的事情。我的单元测试会断言反对viewModel.FieldHtml。我听到的是,我应该把它放在另一个类中,让控制器调用它。但这是它在控制器中的样子。它只是伪代码,所以它并不完美,但它是为了给我所要求的内容提供上下文。
public ActionResult GetValueInput(Guid attributeFieldUid)
{
//you have to pass some stuff into the constructor but essentially this
HtmlHelper html = new HtmlHelper();
AttributeField field = GetAttributeFieldFromDb(attributeFieldUid);
AttributeViewModel viewModel = new AttributeViewModel();
switch(field.type)
{
case Dropdown:
viewModel.FieldHtml = html.DropDownList();
break;
case Text:
viewModel.FieldHtml = html.TextBox();
break;
case Date:
// our own extension method
viewModel.FieldHtml = html.OurDatePicker();
break;
}
}
我最初看到的另一个选项基本上是在剃刀视图上执行此 switch 语句。但我想我喜欢在控制器调用最多的单独类中执行此操作的想法。
这实际上是一个设计问题 - 我问什么实现它的方法最有意义?
您可以为此编写一个自定义 HTML 帮助程序。因此,控制器操作将负责填充视图模型并将其传递给视图:
public ActionResult GetValueInput(Guid attributeFieldUid)
{
AttributeField field = GetAttributeFieldFromDb(attributeFieldUid);
AttributeViewModel viewModel = new AttributeViewModel();
viewModel.FieldType = field.type;
return View(viewModel);
}
然后编写一个帮助程序:
public static class HtmlExtensions
{
public static IHtmlString Field(this HtmlHelper html, FieldType type)
{
switch(field.type)
{
case Dropdown:
return html.DropDownList(... you will probably need some more info on your view model to be passed here to generate a dropdown)
case Text:
return html.TextBox(...);
case Date:
return html.OurDatePicker();
}
return MvcHtmlString.Empty;
}
}
此帮助程序将用于以下视图:
@model AttributeViewModel
@Html.Field(Model.FieldType)
另一种可能性是使用编辑器模板。下面是一个示例。
听起来像是AOP的工作。
这很简单,创建一个自定义属性,您可以在其中指定字段的类型以及所需的任何其他参数。
public class CustomAttribute : Attribute
{
private readonly FieldType _fieldType;
public CustomAttribute(FieldType fieldType)
{
_fieldType = fieldType;
}
public FieldType FieldType { get { return _fieldType; } }
}
并在视图模型上注释属性,例如。
[Custom(FieldType.CheckBox)]
public int SomeField { get; set; }
然后编写一个 html 帮助程序扩展方法,例如。
public static class CustomHtmlHelperExtensions
{
public MvcHtmlString CustomControlFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel,TProperty>> memberExpression)
{
var member = ((MemberExpression)model.Body).Member;
var customAttribute = member.GetAttributes().OfType<CustomAttribute>().Cast<CustomAttribute>().SingleOrDefault();
if(customAttribute == null)
//Perform certain logic if the property doesn't have the attribute specified
//ex. return null;
switch(customAttribute.FieldType)
{
case FieldType.TextBox:
{
//Do something
return htmlHelper.TextBoxFor(memberExpression);
}
default: break;
}
return null;
}
}
这至少应该让你开始:)