3

シンプルな注文追跡アプリケーションである最初のMVC3アプリケーションを書いています。注文と詳細を同時に編集したいのですが。注文を編集すると、編集のActionResultは注文と関連する行を返します(私もEFを使用しています)。

public ActionResult Edit(int id)
    {            
        // Get the order with the order lines
        var orderWithLines = from o in db.Orders.Include("OrderLines")
                                where o.ID == id
                                select o;

        // Not sure if this is the best way to do this.
        // Need to find a way to cast to "Order" type
        List<Order> orderList = orderWithLines.ToList();
        Order order = orderList[0];

        // Use ViewData rather than passing in the object in the View() method.
        ViewData.Model = order;
        return View();            
    }

順序と行は問題なく表示されますが、ページを保存すると、どの行もコントローラーに戻されません。注文のみ。これがビューコードです。

    @model OrderTracker.Models.Order

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

@using (Html.BeginForm())
{
    <fieldset>
        <legend>Order</legend>   

        @Html.HiddenFor(model => model.ID)
        @Html.HiddenFor(model => model.UserId)

        <div>
            @Html.LabelFor(model => model.OrderDate)
        </div>
        <div>
            @Html.EditorFor(model => model.OrderDate)
        </div>
        <div>
            @Html.LabelFor(model => model.Description)
        </div>
        <div>
            @Html.EditorFor(model => model.Description)
        </div>                   

        <table>
            <tr>
                <th>
                    Description
                </th>
                <th>
                    Quantity
                </th>
                <th>
                    Weight
                </th>
                <th>
                    Price
                </th>
                <th></th>
            </tr>
        @foreach (var line in Model.OrderLines)
        { 
            <tr>
                <td>
                    @Html.EditorFor(modelItem => line.Description)
                </td> 
                <td>
                    @Html.EditorFor(modelItem => line.Quantity)
                </td> 
                <td>
                    @Html.EditorFor(modelItem => line.Weight)
                </td> 
                <td>
                    @Html.EditorFor(modelItem => line.Price)
                </td>
            </tr>
        }
        </table>


        <p>
            <input type="submit" value="Save" />
        </p> 

    </fieldset>    
}

注文データだけでなく、ラインデータを保存するための最良の方法についてのガイダンスを教えてもらえますか?

ありがとう。

4

3 に答える 3

7

あなたが直面している問題は、ICollection<T>コントロールによって生成された名前に関連しています。これはPhilHaackによる詳細な議論と彼による解決策です(@Html拡張メソッドに関して;彼のブログ投稿の最後にあるリンクからサンプルプロジェクトをダウンロードしてください)。この投稿はMVC/MVC2を対象としています。ただし、MVC3には引き続き適用できます。

または、ハックを追跡したくない場合は、エンティティモデルを選択できEditorTemplateますOrderLine

手順は次のとおりです。

1)()の下にエディターテンプレートを作成します。の下にViews ->Shared -> EditorTemplates -> OrderLine.cshtmlという名前のフォルダーを作成することが重要です。テンプレート名は、テンプレートを作成するEntityModelと同じである必要があります。したがって、名前)EditorTemplatesSharedOrderLine.cshtml

ここに画像の説明を入力してください

2) OrderLine.cshtmlのコード

@model OrderTracker.Models.OrderLine
@{
    Layout = null;
}

<!DOCTYPE html>
@Html.HiddenFor(modelItem => Model.id)
<tr>
<td>
    @Html.EditorFor(modelItem => Model.Description)
</td> 
<td>
    @Html.EditorFor(modelItem => Model.Quantity)
</td> 
<td>
    @Html.EditorFor(modelItem => Model.Weight)
</td> 
<td>
    @Html.EditorFor(modelItem => Model.Price)
</td>
</tr>

3)EditorForこのコードでビューを編集します( OrderLinesコレクションに使用したことに注意してください)

@model OrderTracker.Models.Order

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

@using (Html.BeginForm())
{
    <fieldset>
        <legend>Order</legend>   

        @Html.HiddenFor(model => model.ID)
        @Html.HiddenFor(model => model.UserId)

        <div>
            @Html.LabelFor(model => model.OrderDate)
        </div>
        <div>
            @Html.EditorFor(model => model.OrderDate)
        </div>
        <div>
            @Html.LabelFor(model => model.Description)
        </div>
        <div>
            @Html.EditorFor(model => model.Description)
        </div>                     
        <div>
        <table>
            <tr>
                <th>
                    Description
                </th>
                <th>
                    Quantity
                </th>
                <th>
                    Weight
                </th>
                <th>
                    Price
                </th>
            </tr>
            @Html.EditorFor(model => model.OrderLines)
            </table>
        </div>
        <p>
            <input type="submit" value="Save" />
        </p> 

    </fieldset>    
}

4)ポストバックで、値が表示されます

ここに画像の説明を入力してください

于 2012-06-24T00:40:39.393 に答える
0

フレームワークはフォームをモデルに変換するように設計されているため、MVCを使用するとかなり簡単になります。

[HttpGet]
public ActionResult Edit(int id)
{
    // (you can probably rewrite this using a lambda
    var orderWithLines = from o in db.Orders.Include("OrderLines")
                         select o;

    // Use ViewData rather than passing in the object in the View() method.
    ViewData.Model = orderWithLines.FirstOrDefault(x => x.ID = id);
    return View();
}

[HttpPost]
public ActionResult Edit(OrderTracker.Models.Order model)
{
    if (ModelState.IsValid)
    {
        // call the service layer / repository / db to persist the object graph
        _service.Save(model); // this assumes your view models are the same as your domain
    }
}
于 2012-06-23T06:59:12.393 に答える
0

問題は、foreachが生成する生のhtmlを見ると、注文行ごとに一意のIDが生成されないため、フォームがポストバックされたときにモデルをバインドできないことにあります。

foreachをforループに変更してから、インデックスを使用して各順序行を参照します。これにより、フォームで一意のIDを生成できるようになり、モデルがポストバックされたときにモデルにバインドできるようになります。

例えば

@for (var counter = 0; counter < Model.OrderLines.Count(); counter++)

    { 
        <tr>
            <td>
                @Html.EditorFor(modelItem => Model.OrderLines[counter].Description)
            </td> 
            <td>
                @Html.EditorFor(modelItem => Model.OrderLines[counter].Quantity)
            </td> 
            <td>
                @Html.EditorFor(modelItem => Model.OrderLines[counter].Weight)
            </td> 
            <td>
                @Html.EditorFor(modelItem => Model.OrderLines[counter].Price)
            </td>
        </tr>
    }
    </table>
于 2012-06-23T15:28:06.957 に答える