문제

이 질문을 하는 데 유용한 간단한 테스트 시나리오가 있습니다.제품에는 여러 구성요소가 있을 수 있으며, 구성요소는 여러 제품에 속할 수 있습니다.EF는 클래스를 생성했으며 다음과 같이 클래스를 축소했습니다.

public partial class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Component> Components { get; set; }
}
public partial class Component
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Product> Products { get; set; }
}

구성 요소 생성은 다음 컨트롤러 작업을 통해 수행됩니다.

public ActionResult Create(int ProductId)
{
    Product p = db.Products.Find(ProductId);
    Component c = new Component();
    c.Products.Add(p);
    return PartialView(c);
} 

[HttpPost]
public ActionResult Create(Component model)
{
    db.Components.Add(model);
    db.SaveChanges();
}

GET 메서드에서 반환된 뷰는 다음과 같습니다.

@model Test.Models.Product

<fieldset>
    <legend>Product</legend>
    <div class="display-label">Name</div>
    <div class="display-field">@Model.Name</div>
</fieldset>

@Html.Action("Create", "Component", new {ProductId = Model.Id}) 
<p>
    @Html.ActionLink("Edit", "Edit", new { id=Model.Id }) |
    @Html.ActionLink("Back to List", "Index")
</p>

위의 내용을 통해 동일한 페이지에서 구성 요소 생성이 처리되는 것을 볼 수 있습니다. Html.Action - 해당 뷰의 코드는 다음과 같습니다.

@model Test.Models.Component
@using Test.Models

<script type="text/javascript">
    function Success() {
        alert('ok');
    }
    function Failure() {
        alert('err');
    }
</script>
@using (Ajax.BeginForm("Create", "Component", new AjaxOptions
{
    HttpMethod = "Post",
    OnSuccess = "Success",
    OnFailure = "Failure"
}))
{
    <fieldset>
        <legend>Components</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
        @Html.HiddenFor(x => x.Products.First().Id)
        @Html.HiddenFor(x => x.Products)
        @foreach (Product p in Model.Products)
        {
            @Html.Hidden("Products[0].Id", p.Id)
        }
        @foreach (Product p in Model.Products)
        {
            @Html.Hidden("[0].Id", p.Id)
        }
    </fieldset>
    <input type="submit" value="go" />
}

좋아요.그래서 이것이 내가 어려움을 겪고 있는 것입니다:나는 필요하다 model [HttpPost]back의 매개변수를 올바르게 채워야 합니다. 즉,null 제품이 있는 새 구성 요소를 만들 수 없으므로 여기에는 Product가 포함되어야 합니다.제품을 얻으려면 제품 ID를 통해 검색해야 합니다.나는 다음을 할 수 있을 것으로 기대합니다:

model.Products.Add(db.Products.Find(model.Products.First().Id));

또는 이에 의존하는 그런 것 model 아이디를 받고 있습니다.이는 뷰가 아마도 숨겨진 필드에 ID를 배치해야 함을 의미하며 내 뷰 코드에서 볼 수 있듯이 이를 채우려고 여러 번 시도했지만 모두 실패했습니다.

일반적으로 나는 올바른 명명법을 생성하는 역할을 담당하는 *For 메소드를 선호합니다..Products가 단수(.Product)인 경우 다음과 같이 참조할 수 있습니다. x => x.Product.Id 다 괜찮을 텐데 복수형이라 그럴 수가 없어요 x => x.Products.Id 그래서 나는 노력했다 x => x.Products.First().Id 올바른 값을 컴파일하고 생성하지만 이름을 얻습니다. Id (모델 바인더가 다음과 같이 생각하기 때문에 이는 잘못된 것입니다. Component.Id 그리고는 아니다 Component.Products[0].Id.

나의 두 번째 시도는 HiddenFor 반복하다(내가 하려는 것처럼 EditorFor):

@Html.HiddenFor(x => x.Products)

하지만 그것은 아무것도 생성하지 않습니다. 이 도우미가 반복하지 않는다는 것을 읽었습니다.나는 노력했다 x => x.Products.First() 하지만 그것은 심지어 컴파일되지도 않습니다.마지막으로 *For를 버리고 이름을 직접 코딩하기로 결정했습니다.

@foreach (Product p in Model.Products)
{
    @Html.Hidden("Products[0].Id", p.Id)

그리고 그게 맞는 것처럼 보이지만 포스트백에서는 내 값을 볼 수 없습니다(Products.Count == 0).일부 게시물에서 형식이 다음과 같아야 한다는 것을 보았습니다. [0].Id 하지만 그것도 작동하지 않습니다.으르렁...

나는 다음과 같이 코딩할 수 있다고 생각합니다.

@Html.Hidden("ProductId", p.Id)

그런 다음 내 컨트롤러 작업을 다음과 같이 다시 선언합니다.

[HttpPost] ActionResult Create(Component model, int ProductId)

그런데 그건 좀 이상한 것 같아요.이것이 그렇게 어렵다는 것을 믿기 어렵습니다.누구든지 도와줄 수 있나요?

  • 이자형

추신.관심 있는 사람이 있으면 다운로드할 수 있는 프로젝트가 있습니다.

도움이 되었습니까?

해결책

그런 글을 쓰는 대신 foreach 루프는 편집기 템플릿을 사용해 보십시오:

<fieldset>
    <legend>Components</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.Name)
    </div>

    <div class="editor-field">
        @Html.EditorFor(model => model.Name)
        @Html.ValidationMessageFor(model => model.Name)
    </div>

    @Html.EditorFor(x => x.Products)
</fieldset>

해당 편집기 템플릿 내부(~/Views/Shared/EditorTemplates/Product.cshtml)

@model Product
@Html.HiddenFor(x => x.Id)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top