簡體   English   中英

將多種形式之一從編輯器模板提交到控制器操作

[英]Submitting one of multiple forms from editor template to a controller action

我有一個顯示帶有動態任務列表的清單的應用程序。 目前,所有任務都有2個單選按鈕:一個用於“完成”,一個用於“未完成”。 稍后,我將添加新的任務類型(文本框等)。

主視圖調用一個創建每個任務的編輯器模板。 清單模型將任務保留在List<Task>類型的屬性“ Tasks”中。 這很好顯示,但是在表單提交上有麻煩。

我希望每個任務獨立保存,因此我在編輯器模板中的控件周圍放置了<form>元素。

調節器

public class CheckController : Controller
{
    [HttpGet]
    public ActionResult Index()
    {
        var checklist = new Checklist();
        GetData(checklist);
        return View(checklist);
    }

    [HttpPost]
    public ActionResult Index(Task model)
    {
        var task = (Task)model;
        return Content($"Save Task:{task.TaskId} Value:{task.IsDone}");
    }
}

楷模

public class Checklist
{
    public List<Task> Tasks { get; set; }
    public Checklist()
    {
        Tasks = new List<Task>();
    }
}

public class Task
{
    public int TaskId { get; set; }
    public string TaskName { get; set; }
    public bool IsDone { get; set; }
}

查看

@model Checkpoint.Models.Checklist
<table>
    @Html.EditorFor(x => x.Tasks);
</table>


@model Checkpoint.Models.Task
<tr>
    <td>@Model.TaskName</td>
    <td data-ftid="@Model.TaskId">
        @{
            using (Html.BeginForm("Index", "Check", FormMethod.Post))
            {
                @Html.HiddenFor(x => x.TaskId)
                @Html.RadioButtonFor(x => x.IsDone, false)<span>Incomplete</span>
                @Html.RadioButtonFor(x => x.IsDone, true)<span>Complete</span>
                <button role="button" type="submit" name="taskAction">Submit</button>
            }
        }
    </td>
</tr>

呈現的HTML

<tr>
    <td>First thing</td>
    <td>
        <form action="/Checklist" method="post">
            <input id="Tasks_0__TaskId" name="Tasks[0].TaskId" type="hidden" value="1" />
            <input checked="checked"id="Tasks_0__IsDone" name="Tasks[0].IsDone" type="radio" value="False" />
            <span>Incomplete</span>
            <input id="Tasks_0__IsDone" name="Tasks[0].IsDone" type="radio" value="True" 
            <span>Complete</span>
            <button role="button" type="submit" name="taskAction">Submit</button>
        </form>
    </td>
</tr>
<tr>
    <td>Second thing</td>
    <td>
        <form action="/Checklist" method="post">
            <input id="Tasks_1__TaskId" name="Tasks[1].TaskId" type="hidden" value="2" />
            <input checked="checked" id="Tasks_1__IsDone" name="Tasks[1].IsDone" type="radio" value="False" />
            <span>Incomplete</span>
            <input id="Tasks_1__IsDone" name="Tasks[1].IsDone" type="radio" value="True" />
            <span>Complete</span>
            <button role="button" type="submit" name="taskAction">Submit</button>
        </form>
    </td>
</tr>

這確實提交了請求,但是數據如下所示:

Tasks[1].TaskId: 1
Tasks[1].IsDone: True

當它到達控制器動作(接受Task類型)時,屬性值為null。

如何在控制器操作中正確獲取任務數據? 還是我要以完全錯誤的方式進行此操作?

獎勵:添加新任務類型的最佳方法是什么?

由於您不打算一次提交所有集合,因此您將需要丟失模型名稱的索引。

Tasks[0].TaskId

調整您的視圖。 變量名稱“ task”需要與action參數匹配,因為HtmlHelpers將基於此字符串生成名稱屬性。

@model Checkpoint.Models.Checklist
<table>
    @foreach(Task task in Model.Tasks)
    {
        @Html.EditorFor(m => task)
    }
</table>

呈現的html看起來像

<input id="task_TaskId" name="task.TaskId" type="hidden" value="1">
...

該操作需要一個“任務”參數來匹配以綁定其值

[HttpPost]
public ActionResult Index(Task task)
{
    return Content($"Save Task:{task.TaskId} Value:{task.IsDone}");
}

如果我們使用局部視圖而不是編輯器模板,則可以稍微放寬對“任務”的名稱依賴。

@model Checkpoint.Models.Checklist
<table>
    @foreach(Task t in Model.Tasks)
    {
        @Html.PartialView("_TaskForm", t)
    }
</table>

並且您的編輯器模板內容將完全相同。

_TaskForm

@model Checkpoint.Models.Task
<tr>
    <td>@Model.TaskName</td>
    <td data-ftid="@Model.TaskId">
        @{
            using (Html.BeginForm("Index", "Check", FormMethod.Post))
            {
                @Html.HiddenFor(x => x.TaskId)
                @Html.RadioButtonFor(x => x.IsDone, false)<span>Incomplete</span>
                @Html.RadioButtonFor(x => x.IsDone, true)<span>Complete</span>
                <button role="button" type="submit" name="taskAction">Submit</button>
            }
        }
    </td>
</tr>

和渲染的html

<input id="TaskId" name="TaskId" type="hidden" value="1">
...

上面所有的問題是html id屬性將不是唯一的。 因此,如果這很關鍵,則需要手動迭代該集合以手動構建每個表單,以便您可以精確地指定id值。 也就是說,您將丟失小型的模塊化編輯器模板。

讓框架自動生成“唯一” ids ...我們重寫name屬性(注意“ Name”的大小寫),我們有:

@model Checkpoint.Models.Checklist
<table>
    @for(int i = 0; i < Model.Tasks.Count; i++)
    {
        <tr>
           <td>@Model.Tasks[i].TaskName</td>
           <td data-ftid="@Model.Tasks[i].TaskId">
               @using (Html.BeginForm("Index", "Check", FormMethod.Post))
               {
                   @Html.HiddenFor(x => Model.Tasks[i].TaskId, new { Name="TaskId" })
                   @Html.RadioButtonFor(x => Model.Tasks[i].IsDone, false, new { Name="IsDone" })<span>Incomplete</span>
                   @Html.RadioButtonFor(x => Model.Tasks[i].IsDone, true, new { Name="IsDone" })<span>Complete</span>
                   <button role="button" type="submit" name="taskAction">Submit</button>
              }
           </td>
       </tr>
    }
</table>

通過拖放幫助器並手動創建控件,我可以使用“編輯器模板”來實現此目的。

@model Checkpoint.Models.Task
<tr>
    <td>@Model.TaskName</td>
    <td data-ftid="@Model.TaskId">
        @using (Html.BeginForm("Index", "Check", FormMethod.Post))
        {
            <input name="TaskId" type="hidden" value="@Model.TaskId" />
            <input name="IsDone" type="radio" value="True" @Html.Raw(Model.IsDone ? "checked=checked" : null) />
            <span>Complete</span>
            <input name="IsDone" type="radio" value="False" @Html.Raw(!Model.IsDone ? "checked=checked" : null) />
            <span>Incomplete</span>
            <button role="button" type="submit" name="taskAction" value="@Model.TaskId">Submit</button>
        }
    </td>
</tr>

我對此並不是很滿意,而是選擇了@Jasen的局部視圖解決方案。 通過覆蓋助手中的'id'屬性,我可以獲得唯一的元素ID。 我使用TaskId,因為它是唯一的,但否則可以從主視圖傳遞循環索引。

@model Checkpoint.Models.Task
<tr>
    <td>@Model.TaskName</td>
    <td data-ftid="@Model.TaskId">
        @using (Html.BeginForm("Index", "Check", FormMethod.Post))
        {
            @Html.HiddenFor(x => x.TaskId, new { id = "Task_" + Model.TaskId + "_hidIsDone" })
            @Html.RadioButtonFor(x => x.IsDone, false, new { id = "Task_"+ Model.TaskId + "_radIsDoneF" })<span>Incomplete</span>
            @Html.RadioButtonFor(x => x.IsDone, true, new { id = "Task_" + Model.TaskId + "_radIsDoneT" })<span>Complete</span>
            <button role="button" type="submit" name="taskAction">Submit</button>
        }
    </td>
</tr>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM