2012-06-23 3 views
3

간단한 주문 추적 응용 프로그램 인 MVC3 응용 프로그램을 처음 작성했습니다. 주문과 세부 사항을 동시에 수정하고 싶습니다. 주문을 편집 할 때 편집을위한 ActionResult가 주문과 관련 라인을 반환합니다 (나는 EF도 사용하고 있습니다).MVC보기에서 여러 개체 저장

주문 및 행은 아무런 문제없이 표시되지만 페이지를 저장하면 컨트롤러에 다시 전달 된 행이 없습니다. 주문 만. 다음은 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>  
} 

라인 데이터와 주문 데이터를 저장하는 가장 좋은 방법에 대한 지침을 얻을 수 있습니까?

감사합니다.

답변

7

문제는 ICollection<T> 컨트롤에 의해 생성 된 이름과 관련이 있습니다. 여기에 detailed discussion by Phil Haack과 해결책이 있습니다 (@Html 확장 방법). 블로그 게시물의 끝에 제공된 링크에서 샘플 프로젝트를 다운로드하십시오. 이 게시물은 MVC/MVC2를 대상으로합니다. 그러나 여전히 MVC3에 적용 가능합니다.

또는 해킹을 따르고 싶지 않은 경우 OrderLine 엔티티 모델의 경우 EditorTemplate을 선택할 수 있습니다.

다음은 단계입니다.

1) (Views ->Shared -> EditorTemplates -> OrderLine.cshtml) 에서 편집기 템플릿을 만듭니다 그것은 Shared에서 EditorTemplates라는 이름의 폴더를 생성하는 것이 중요합니다, 당신은 templete입니다을 만들려는 템플릿 이름이 EntityModel과 동일해야한다; 따라서 이름 OrderLine.cshtml)

enter image description here

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> 
이 코드 (내가 OrderLines 수집에 EditorFor을 사용한 적이 있습니다)

@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) 다시이 값을 볼 수와 편집보기를

3)

enter image description here

+0

ASP MVC 5에서 작동하지 않았습니다. 모든 포인터는 일괄 처리 Ienumerable을 보내주십시오. transformer

+0

@transformer는 MVC5에서 정상적으로 작동합니다. 너를 위해 무엇이 실패하고 있는가? 'Order'모델에는 'OrderLine'항목의 목록이 있습니다. 내 답변에 포인트 1 & 3에 세심한주의를 기울이십시오. github 저장소에 샘플 코드가 있습니까? –

0

MVC를 사용하면 프레임 워크가 모델을 모델로 변환하기 위해 설계 되었기 때문에 MVC를 사용하는 것이 훨씬 간단합니다. 당신이 그것을 주문 라인의 각각에 대해 고유 한 ID를 생성하지 않습니다 때문에 형태 인 경우 모델을 결합 할 수 없습니다 생산 원시 HTML 보면

[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 
    } 
} 
0

문제는 foreach는 함께 다시 게시했습니다.

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> 
+0

나는 이것을 시험해 보았다. 컬렉션에 색인을 사용할 수 없습니다. 나는 생성 된 HTML을 검사하여 각 행에 대해 중복 된 HTML 요소 ID가 있음을 알 수 있습니다 (이것이 문제인지 확실하지 않음). 그래서 뷰 ​​요소를 컨트롤러에 바인딩하는 다른 방법이 필요해 보입니다. 내가 이해할 수없는 것은 뷰가 컨트롤러에 바인딩되는 방식입니다. 뷰와 컨트롤러가 HTML 요소 ID에서 일치합니까? 명확한 정의에 대한 링크가 있으면 감사하겠습니다. – user1476207

+0

죄송합니다. 주문 라인이 아니어야합니다. 컨트롤러에 다시 게시하면 ID를 사용하여 모델을 바인딩합니다 (예 : ID가 "OrderLines_2__Description"인 항목은 두 x 째 OrderLine에 대한 설명 필드입니다. –