C# ASP.NET MVC呈现视图,并在动态生成的视图验证失败时保留值
我正在尝试构建一个动态生成的视图。创建操作的控制器类如下所示C# ASP.NET MVC呈现视图,并在动态生成的视图验证失败时保留值,c#,asp.net-mvc,dynamic-forms,C#,Asp.net Mvc,Dynamic Forms,我正在尝试构建一个动态生成的视图。创建操作的控制器类如下所示 public ActionResult Create() { List<FormMetadata> formItems = GetFormItems(); return View(formItems); } <% using (Html.BeginForm()) {%> <table> <% foreach (var item in Mo
public ActionResult Create()
{
List<FormMetadata> formItems = GetFormItems();
return View(formItems);
}
<% using (Html.BeginForm())
{%>
<table>
<% foreach (var item in Model)
{
if (!item.IsActive)
{
continue;
}
%>
<tr>
<td>
<%=Html.Encode(item.DisplayValue)%>
</td>
<td>
<%
if (item.FieldType == "TextBox")
{%>
<%=Html.TextBox(item.Field, null, new { tabindex = item.SortOrder })%>
<%}
if (item.FieldType == "CheckBox")
{%>
<%=Html.CheckBox(item.Field, false, new { tabindex = item.SortOrder })%>
<%}
%>
</td>
<td>
</td>
</tr>
<%} %>
</table>
如何在保留为此场景输入的值的同时显示有验证错误的视图?EDIT2
我已经创建了一个工作的快速示例项目。有一件事我不喜欢,那就是我不能把清单传递给别人。我必须每次创建空白列表,并从文本框中读取所有值,并将其保存在列表中,并将此更新的列表提供给新视图。下一轮同样的事情。但它是有效的
基本上:
public ActionResult About() {
List<FormMetaData> formItems = GetFormItems();
return View(formItems);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult About(FormCollection form)
{
List<FormMetaData> formItems = GetFormItems();
//TryUpdateModel(formItems);
// update project members
foreach (var key in form.AllKeys) {
if (key.ToString().StartsWith("TextBox")) {
string field = (key.ToString().Replace("TextBox", ""));
if (!string.IsNullOrEmpty(form.Get(key.ToString()))) {
formItems.Find(delegate(FormMetaData t) { return t.Field == field; }).Value = form.Get(key.ToString());
}
else { }
// this.ProjectRepository.DeleteMemberFromProject(id, userId);
}
}
ModelState.AddModelError("test", "this is a test error");
if(ModelState.IsValid)
{
///
}
else
{
return View(formItems);
}
return View(formItems);
}
private List<FormMetaData> GetFormItems() {
List<FormMetaData> output = new List<FormMetaData>();
FormMetaData temp1 = new FormMetaData("TextBox",true,"temp1","displayText1");
FormMetaData temp2 = new FormMetaData("TextBox", true, "temp2", "displayText2");
output.Add(temp1);
output.Add(temp2);
return output;
}
这应该能奏效
因此,在一个简单的例子中,您可以得到如下结果:
<%=Html.TextBox(item.Field, **item.Value**, new { tabindex = item.SortOrder })%>
if(ModelState.isValid){
//code when it works
}
else{
return View(formItems) // these should contain the just added values
}
public ActionResult Create()
{
List<FormMetadata> formItems = GetFormItems();
return View(formItems);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(List<FormMetadata> formItems)
{
if(ModelState.isValid)
{
MyUpdate()
save()
}
else
{
return view(formItems)
}
}
你的看法是:
<% using (Html.BeginForm()) {%>
<table>
<% foreach (var item in Model) {
if (!item.isActive) {
continue;
} %>
<tr>
<td>
<%=Html.Encode(item.DisplayValue)%>
</td>
<td>
<% if (item.FieldType == "TextBox") {%>
<%=Html.TextBox("TextBox"+item.Field, item.Value)%>
<%} if (item.FieldType == "CheckBox") {%>
<%=Html.CheckBox("Value")%>
<%}%>
</td>
<td>
</td>
</tr>
<%} %>
<p>
<input type="submit" value="submit" />
</p>
<% } %>
</table>
<%
if (item.FieldType == "TextBox")
{%>
<%=Html.TextBox(item.Field, **item.Value**, new { tabindex = item.SortOrder })%>
<%}
if (item.FieldType == "CheckBox")
{%>
<%=Html.CheckBox(item.Field, **item.Value**, new { tabindex = item.SortOrder })%>
<%}
我会先查看NerdDinner,基本上使用相同的方法。我现在使用以下方法,目前只使用文本框 这一观点已经过时
<%
for (int i = 0; i < Model.Count; i++)
{
var name = "formItems[" + i + "].Field";
var htmlAttributes = new Dictionary<string, object>
{
{"tabindex", Model[i].SortOrder},
{"class", Model[i].ClientSideValidation}
};
%>
<div> <%=Html.Encode(Model[i].DisplayValue)%>
<%=Html.TextBox(name, Model[i].DefaultValue, htmlAttributes)%>
<%= Html.ValidationMessage(Model[i].Field) %>
</div>
<% } %>
以及控制器的动作方法
得到
张贴代码的一部分
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(List<FormMetadata> formItems)
{
var formDefinition = new List<FormMetadata>();
try
{
if (HttpContext.Cache[FormCacheKey] != null)
{
formDefinition = HttpContext.Cache[FormCacheKey] as List<FormMetadata>;
}
else
{
formDefinition = GetFormItems();
HttpContext.Cache[FormCacheKey] = formItems;
}
var formValues = new Dictionary<string, string>();
for (int i = 0; i < formDefinition.Count; i++)
{
var key = formDefinition[i].Field;
var value = formItems[i].Field ?? string.Empty;
我尝试过这种方法。HttpVerbs.Post Create操作中的formItems在控制器中始终发送空值。这可能是因为默认modelbinder将尝试将文本框中的值绑定到您的键首值。所以实际上它一定是这样的:现在它尝试将文本框中的值绑定到Model.item.value。当然,您可以按自己喜欢的方式命名。编辑此答案时,我会根据我的猜测对问题进行详细说明。我发现要绑定到复杂类型的列表,视图中的名称需要编制索引。因此,我现在使用for循环,而不是在视图中使用foreach循环。这会将值绑定到我的列表。使用缓存在Http.Get Create操作中缓存formitem,然后获取字段和值的集合。这似乎现在起作用了。你能把你的最终答案张贴在一个单独的答案中,还是自己编辑?对于有相同问题的人来说可能很方便:。您能解释一下在什么情况下这会变得有用吗。看起来您正在尝试制作某种EAV系统。
<%
for (int i = 0; i < Model.Count; i++)
{
var name = "formItems[" + i + "].Field";
var htmlAttributes = new Dictionary<string, object>
{
{"tabindex", Model[i].SortOrder},
{"class", Model[i].ClientSideValidation}
};
%>
<div> <%=Html.Encode(Model[i].DisplayValue)%>
<%=Html.TextBox(name, Model[i].DefaultValue, htmlAttributes)%>
<%= Html.ValidationMessage(Model[i].Field) %>
</div>
<% } %>
public ActionResult Create()
{
List<FormMetadata> formItems = GetFormItems();
HttpContext.Cache[FormCacheKey] = formItems;
return View(formItems);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(List<FormMetadata> formItems)
{
var formDefinition = new List<FormMetadata>();
try
{
if (HttpContext.Cache[FormCacheKey] != null)
{
formDefinition = HttpContext.Cache[FormCacheKey] as List<FormMetadata>;
}
else
{
formDefinition = GetFormItems();
HttpContext.Cache[FormCacheKey] = formItems;
}
var formValues = new Dictionary<string, string>();
for (int i = 0; i < formDefinition.Count; i++)
{
var key = formDefinition[i].Field;
var value = formItems[i].Field ?? string.Empty;