视图显示不同的值,然后在其模型中显示

时间:2018-07-18 12:06:17

标签: c# asp.net-mvc asp.net-mvc-4

简短概述

我有一个非常奇怪的错误,而且我绝对不知道它从哪里来。我要创建一个网页,您可以在其中修改表,并可以从该表中生成数据库中的表。为此,我正在使用ASP .NET MVC 4,并且已经能够在数据库中修改和创建表,但是我有一个小的“ +”按钮,我想在其中将单元格插入表(模型)中。 >

问题

  

它已经可以工作了,但是它总是将其插入到最后一个索引中,并且名称也等于前一个索引。 (与使用“-”按钮删除相同)

以下是两个屏幕截图:
点击之前before 点击后after

代码

为实现这一点,我创建了两个模型:

CreateTableModel

我用一列初始化模型。 (我有更多不相关的属性和功能)

public class CreateTableModels
{
    public CreateTableModels()
    {
        Columns = new List<CreateTableColumnModels>() { new CreateTableColumnModels(){ PrimaryKey = true } };
    }

    [Required]
    [UniqueNamesValidation(ErrorMessage="Alle Namen müssen unique sein")]
    [Display(Name = "Columns")]
    public List<CreateTableColumnModels> Columns { get; private set; }

    //more properties...

此模型具有 CreateTableColumnModels 列表:

public class CreateTableColumnModels
{
    public CreateTableColumnModels()
    {
        Name = "name";
        NotNull = false;
        PrimaryKey = false;
        Length = 1;
    }

    [Required]
    [Display(Name = "Typ")]
    public System.Data.SqlDbType Type { get; set; }

    [Key]
    [Required(ErrorMessage = "Darf nicht leer sein!")]
    [RegularExpression(@"^[A-Za-z0-9]+$", ErrorMessage = "Nur Buchstaben und Zahlen sind erlaubt")]
    [Display(Name = "Name")]
    public string Name { get; set; }

    //more properties...

控制器

在控制器中,我想在模型中插入一列(如果按下按钮,它将通过addCell发送索引)。该列的名称应为“已添加”。如果我添加新列,则效果很好。

public class CreateTableController : Controller
{
    public ViewResult Index(CreateTableModels model, int count = 1, int? addCell = null, int? removeCell = null, bool createTable = false)
    {
        if (addCell != null)
        {
            model.Columns.Insert(addCell.Value, new CreateTableColumnModels() { Name = "ADDED", Type = System.Data.SqlDbType.Float });
        }

查看

我确实将几乎整个观点都放在了这里,因为我完全不知道问题所在。

<h2>CreateTable</h2>

@using (Html.BeginForm("Index", "CreateTable", FormMethod.Get))
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    @Html.ValidationSummary(true)
</div>
<table id="table" class="table">
    <thead>
        <tr>
            <th>@Html.LabelFor(model => model.Columns.FirstOrDefault().Type)</th>
            <th>@Html.LabelFor(model => model.Columns.FirstOrDefault().Length)</th>
            <th>@Html.LabelFor(model => model.Columns.FirstOrDefault().Precision)</th>
            <th>@Html.LabelFor(model => model.Columns.FirstOrDefault().Name)</th>
            <th>@Html.LabelFor(model => model.Columns.FirstOrDefault().NotNull)</th>
            <th>@Html.LabelFor(model => model.Columns.FirstOrDefault().PrimaryKey)</th>
        </tr>
    </thead>
    <tbody>
        @for (int i = 0; i < @Model.Columns.Count; i++)
        {
            <tr>
                <td>
                    <div id="TableSelection">
                        @Html.DropDownListFor(m => Model.Columns[i].Type, new SelectList(Model.Columns[i].Types), new { @ID = "typeSelection", @class = "form-control", @style = "width:150px;" })
                    </div>
                </td>
                <td>
                    <div id="Length">
                        @Html.TextBoxFor(m => Model.Columns[i].Length, new { @ID = "length", @class = "form-control", @type = "number", @style = "width:80px", @disabled = "disabled" })
                        @Html.ValidationMessageFor(m => Model.Columns[i].Length)
                    </div>
                </td>
                <td>
                    <div id="Precision">
                        @Html.TextBoxFor(m => Model.Columns[i].Precision, new { @ID = "precision", @class = "form-control", @type = "number", @style = "width:80px", @disabled = "disabled" })
                        @Html.ValidationMessageFor(m => Model.Columns[i].Precision)
                    </div>
                </td>
                <td>
                    <div id="Name">
                        @Html.TextBoxFor(model => Model.Columns[i].Name, new { @class = "form-control", @style = "width:150px" })
                        @Html.ValidationMessageFor(model => Model.Columns[i].Name)
                    </div>
                </td>
                <td>
                    <div id="NotNull">
                        @Html.CheckBoxFor(model => Model.Columns[i].NotNull, new { @ID = "notNull", @checked = Model.Columns[i].NotNull, @class = "checkbox" })
                    </div>
                </td>
                <td>
                    <div id="PrimaryKey">
                        @Html.CheckBoxFor(x => Model.Columns[i].PrimaryKey, new { @ID = "primaryKey", @checked = Model.Columns[i].PrimaryKey, @class = "checkbox" })
                    </div>
                </td>
                <td>
                    <div>
                        <button type="submit" class="btn btn-default" name="addCell" value="@i">+</button>
                        <button type="submit" class="btn btn-default" name="removeCell" value="@i">-</button>
                    </div>
                </td>
            </tr>
        }
    </tbody>
</table>

<div align="left" class=" form-group" style="display: flex; flex-direction: row; justify-content: flex-start; align-items: center;">
    <div>
        @Html.LabelFor(model => model.TableName, new { @class = "control-label col-md-2" })
    </div>
    <div class="text-center control-form">
        @Html.EditorFor(model => model.TableName, new { @class = "text-center control-form" })
        @Html.ValidationMessageFor(model => model.TableName)
    </div>
    <div>
        <button type="submit" style="margin-left:10px; margin-right:10px;" name="createTable" value="true" class="btn btn-success">Create</button>
    </div>
    <div>
        @if (Model.WorkDone != null && (bool)Model.WorkDone)
        {
            <label style="font-size:medium" class="label label-success">Alle Änderungen wurden gespeichert!</label>
        }
        else if (Model.WorkDone != null)
        {
            <label style="font-size:medium" class="label label-danger">Es ist etwas schief gelaufen!</label>
        }
    </div>
</div>
}

调试

如果我调试它直到视图结束,它也具有正确的值。 debug

我唯一能想到的改变是@RenderBody()文件中的_Layout.cshtml。有谁有类似的东西或可以帮助我吗?已经感谢您读完了:)

1 个答案:

答案 0 :(得分:2)

问题在于,当您提交收藏集时,发布的值将添加到ModelState中。如果我们仅查看Name属性,则会添加以下值

Columns[0].Name // value = "a"
Columns[1].Name // value = "b"
Columns[2].Name // value = "c"

现在,您插入一个新列(例如在第一项之前)。现在模型中的值是

Columns[0].Name // value = "ADDED"
Columns[1].Name // value = "a"
Columns[2].Name // value = "b"
Columns[3].Name // value = "c"

现在,当您返回视图时,您(正确)使用了HtmlHelper方法来生成视图,但是所有生成表单控件的HtmlHelper方法都通过检查来呈现value属性以下(按顺序)

  1. ModelState中的值(如果有)
  2. ViewDataDictionary中的值(如果有)
  3. 模型中的值

此行为的原因在TextBoxFor displaying initial value, not the value updated from code中进行了说明。

for循环的第一次迭代中,您的@Html.TextBoxFor(m => m.Columns[i].Name)ModelState中看到“ a”的值,并在文本框中呈现“ a”(即使型号为“已添加”)。

在第二次迭代中,该值再次从ModelState中获取,因此呈现了“ b”。

在第3次迭代中,该值再次从ModelState中获取,因此呈现了“ c”。

在第4次也是最后一次迭代中,在ModelState的{​​{1}}(或ViewData)中找不到值,因此它从模型中读取值,因此“ c”呈现。

请注意,如果在表单元格中添加了Columns[3].Name,则会看到根据属性值渲染的值,即第1行:“添加”,第2行:“ a”,第3行:“ b”,第4行:“ c”。

要解决此问题,您可以在返回视图之前添加@Model.Columns[i].Name。但是,这样做的副作用是,它还会清除所有验证错误,因此至少ModelState.Clear()无效时,您应该立即返回视图

ModelState

但是,最好的方法是遵循PRG模式并重定向到生成新数据的方法。