【发布时间】:2021-06-04 02:41:43
【问题描述】:
我需要为不同的客户端提供不同的表单,这些表单都可以在后台配置(最终在数据库中)
我最初的想法是为“Form”创建一个对象,该对象具有“FormItem 字典”来描述表单字段。
然后我可以通过执行以下操作来新建一个动态表单(这将来自数据库/服务):
private Form GetFormData()
{
var dict = new Dictionary<string, FormItem>();
dict.Add("FirstName", new FormItem()
{
FieldType = Core.Web.FieldType.TextBox,
FieldName = "FirstName",
Label = "FieldFirstNameLabel",
Value = "FName"
});
dict.Add("LastName", new FormItem()
{
FieldType = Core.Web.FieldType.TextBox,
FieldName = "LastName",
Label = "FieldLastNameLabel",
Value = "LName"
});
dict.Add("Submit", new FormItem()
{
FieldType = Core.Web.FieldType.Submit,
FieldName = "Submit",
Label = null,
Value = "Submit"
});
var form = new Form()
{
Method = "Post",
Action = "Index",
FormItems = dict
};
return form;
}
在我的控制器中,我可以获取表单数据并将其传递到视图中
public IActionResult Index()
{
var formSetup = GetFormData(); // This will call into the service and get the form and the values
return View(formSetup);
}
在视图中,我为每个 FormItems 调用 HtmlHelper
@model Form
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@using FormsSpike.Core.Web
@{
ViewData["Title"] = "Home Page";
}
@using (Html.BeginForm(Model.Action, "Home", FormMethod.Post))
{
foreach (var item in Model.FormItems)
{
@Html.FieldFor(item);
}
}
然后在回发时,我必须遍历表单变量并再次匹配它们。这感觉非常老派,我希望会在某种模型活页夹中完成。
[HttpPost]
public IActionResult Index(IFormCollection form)
{
var formSetup = GetFormData();
foreach (var formitem in form)
{
var submittedformItem = formitem;
if (formSetup.FormItems.Any(w => w.Key == submittedformItem.Key))
{
FormItem formItemTemp = formSetup.FormItems.Single(w => w.Key == submittedformItem.Key).Value;
formItemTemp.Value = submittedformItem.Value;
}
}
return View("Index", formSetup);
}
然后我可以运行一些映射,这将在后台更新数据库。
我的问题是这感觉不对 :o{
我也使用了一个非常简单的 HtmlHelper,但我不能真正使用标准的 htmlHelpers(例如 LabelFor)来创建表单,因为没有模型可以绑定到..
public static HtmlString FieldFor(this IHtmlHelper html, KeyValuePair<string, FormItem> item)
{
string stringformat = "";
switch (item.Value.FieldType)
{
case FieldType.TextBox:
stringformat = $"<div class='formItem'><label for='item.Key'>{item.Value.Label}</label><input type='text' id='{item.Key}' name='{item.Key}' value='{item.Value.Value}' /></ div >";
break;
case FieldType.Number:
stringformat = $"<div class='formItem'><label for='item.Key'>{item.Value.Label}</label><input type='number' id='{item.Key}' name='{item.Key}' value='{item.Value.Value}' /></ div >";
break;
case FieldType.Submit:
stringformat = $"<input type='submit' name='{item.Key}' value='{item.Value.Value}'>";
break;
default:
break;
}
return new HtmlString(stringformat);
}
由于属性(例如 RegExAttribute 的RequiredAttribute)不存在,因此验证也将不起作用。
我的方法有误,还是有更明确的方法来完成这样的表格?
有没有一种方法可以创建一个动态的 ViewModel,它可以从原始设置中创建并仍然保留所有 MVC 的丰富性?
【问题讨论】:
-
你找到解决方案了吗?
-
@Bonner웃 如果您在下面查看,mcintyre321 对此进行了回复。但是,当我移动项目时,我没有进一步研究这个问题。查看aspdatatables.azurewebsites.net 的演示,它似乎做了我想要的事情,但我的示例要复杂得多,可能有 100 个字段。
-
我不喜欢 FormFactory 解决方案,因为模型被传递到解析器中,而且感觉非常有限。我更喜欢 WebForms API 而不是 FormFactory 库,这就是我问的原因。
-
我也遇到过这个问题。我知道你已经离开了这个项目,但只是在这里碰碰运气,你或@BrownCow 找到了不同的解决方案吗?
-
@learner 不,我继续前进:)
标签: asp.net-mvc forms model-view-controller custom-model-binder