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;