ASP MVC 3의 한보기에 두 모델


91

두 가지 모델이 있습니다.

public class Person
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }
}
public class Order
{
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}

SINGLE 뷰에서 두 클래스의 개체를 편집하고 싶으므로 다음과 같은 것이 필요합니다.

@model _try2models.Models.Person
@model _try2models.Models.Order

@using(Html.BeginForm())
{
    @Html.EditorFor(x => x.PersonID)
    @Html.EditorFor(x => x.PersonName)
    @Html.EditorFor(x=>x.OrderID)
    @Html.EditorFor(x => x.TotalSum)
}

물론 이것은 작동하지 않습니다. .cshtml 파일에는 하나의 'model'문만 허용됩니다. 몇 가지 해결 방법이 있습니까?


1
내 대답이 도움이됩니까?
Andrew

나는 ViewBag각각의 in view를 사용 하여 나를 위해 일했습니다. 여러 옵션을 알기 위해 이것을 확인 하고,보기 모델이나 부분보기를 만드는 대신 시간을 절약했습니다
shaijut

답변:


118

두 모델을 모두 포함하는 상위 뷰 모델을 만듭니다.

public class MainPageModel{
    public Model1 Model1{get; set;}
    public Model2 Model2{get; set;}
}

이렇게하면 최소한의 노력으로 나중에 모델을 추가 할 수 있습니다.


2
이 솔루션을 사용할 때 Model1 또는 Model2를 변경하면 MainPageModel에 영향을 줄 수 있습니다. 또한 뷰에 실제로 필요한 것보다 더 많은 데이터가 포함되어 있습니다. MainPage가 이미 다른 컨트롤러에있는 항목의 조합 인 경우 RenderPartial에서 RenderAction으로 전환하면 항목을 깔끔하게 분리 할 수 ​​있습니다. 데메테르의 법칙에 독서 고려 : en.wikipedia.org/wiki/Law_of_Demeter
펜톤에게

1
@Andi-위에서 제안한대로 모델을 만들었습니다. 하지만 컨트롤러를 마우스 오른쪽 버튼으로 클릭하고 Crud 컨트롤러를 만들려고하면 작동하지 않습니까? 어떤 제안? 위 모델에 대한 자동보기를 사용하여 크 러드 컨트롤러를 생성하려면 어떻게해야합니까?
NoviceMe 2012-08-31

2
이 문제를 해결하기 위해 내가 본 모든 접근 방식 중에서 이것이 저에게 가장 잘 맞는 방법입니다. 작동하는 가장 간단한 솔루션입니다.
Ciaran Gallagher

4
"왜 내가 전에 생각하지 않았어?"라고 스스로에게 물을 때의 순간 훌륭한 솔루션
Rafael AMS

1
@Andi 컨트롤러에서 각 모델의 메서드를 어떻게 노출합니까?
Volatil3 2016-06-18

53

튜플을 사용하려면 다음을 수행해야합니다. 뷰에서 모델을 다음과 같이 변경합니다.

@model Tuple<Person,Order>

@html 메서드를 사용하려면 다음을 수행해야합니다.

@Html.DisplayNameFor(tuple => tuple.Item1.PersonId)

또는

@Html.ActionLink("Edit", "Edit", new { id=Model.Item1.Id }) |

Item1은 Tuple 메서드에 전달 된 첫 번째 매개 변수를 나타내며 Item2를 사용하여 두 번째 모델 등에 액세스 할 수 있습니다.

컨트롤러에서 Tuple 유형의 변수를 만든 다음 뷰에 전달해야합니다.

    public ActionResult Details(int id = 0)
    {
        Person person = db.Persons.Find(id);
        if (person == null)
        {
            return HttpNotFound();
        }
        var tuple = new Tuple<Person, Order>(person,new Order());

        return View(tuple);
    }

또 다른 예 : 뷰의 여러 모델


1
절대로 를 사용하지 Tuple영업 이익은 편집 데이터를 원하는되며,이 -이 경우 Tuple양식이 제출 될 때 모델을 바인딩 할 수 있도록 기본 생성자가

결코 말하지 마십시오. 여기서 약간 강합니다.
johnny

47

커스텀 모델을 생성 할 필요가없는 또 다른 옵션은 Tuple <> 을 사용하는 것 입니다.

@model Tuple<Person,Order>

Andi의 답변에 따라 둘 다 포함하는 새 클래스를 만드는 것만 큼 깨끗하지는 않지만 실행 가능합니다.


mvc 3에서는 오류가 발생합니다. 파일에는 하나의 'model'문만 허용됩니다. 그것을 해결하는 방법을 아십니까?
GibboK

1
@GibboK-MVC3에서 잘 사용하고 있습니다. 별도의 두 @model줄 이 없는지 확인 하시겠습니까?
Bobson

3
다음을 사용하여 각 모델의 속성을 가져올 수 있습니다. @Model.Item1.Property@Model.Item2.Propertyfor PersonOrder각각
user2019515

1
내 뷰에서 튜플을 사용했습니다. 하지만 컨트롤러에서 모델 값을 가져올 수 없습니다. 그러나 @Andi가 권장하는 부모 뷰 모델을 사용하는 동안 컨트롤러에서 모델 값을 얻었습니다.
NAREN

1
@StephenMuecke-흠. 나는 그것을 고려한 적이 없지만 당신이 옳습니다. Andrew의 대답에 대한 또 다른 이유는 더 나은 범용입니다. (이 같은) 경량 대안 갈 때, 당신은 기능을 제공합니다.
Bobson 2011

10

매우 평평한 모델을 선호하는 경우보기를 지원하기 위해이 특정보기에 특정한 모델을 만들어야합니다.

public class EditViewModel
    public int PersonID { get; set; }
    public string PersonName { get; set; }
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}

많은 사람들이 AutoMapper를 사용하여 도메인 개체에서 플랫 뷰로 매핑합니다.

뷰 모델의 아이디어는 단지 뷰를 지원한다는 것입니다. 다른보기에 대해 원하는 속성로드가 아닌 해당보기에 필요한 것만 포함하도록보기 당 하나씩 있습니다.


5

좋아요, 모두 이해가 되셨고 저는 모든 조각을 가져 와서 설명을 끝낼 필요가있는 저와 같은 초보자를 돕기 위해 여기에 두었습니다.

@Andrew의 답변에 따라 2 개의 클래스를 보유한 큰 클래스를 만듭니다.

public class teamBoards{
    public Boards Boards{get; set;}
    public Team Team{get; set;}
}

그런 다음 컨트롤러에서 2 개의 모델을 채 웁니다. 때로는 하나만 채우면됩니다. 그런 다음 반환에서 큰 모델을 참조하고 내부에있는 2를 View로 가져갑니다.

            TeamBoards teamBoards = new TeamBoards();


        teamBoards.Boards = (from b in db.Boards
                               where b.TeamId == id
                               select b).ToList();
        teamBoards.Team = (from t in db.Teams
                              where t.TeamId == id
                          select t).FirstOrDefault();

 return View(teamBoards);

보기 상단

@model yourNamespace.Models.teamBoards

그런 다음 큰 모델 콘텐츠를 참조하는 입력 또는 디스플레이를로드합니다.

 @Html.EditorFor(m => Model.Board.yourField)
 @Html.ValidationMessageFor(m => Model.Board.yourField, "", new { @class = "text-danger-yellow" })

 @Html.EditorFor(m => Model.Team.yourField)
 @Html.ValidationMessageFor(m => Model.Team.yourField, "", new { @class = "text-danger-yellow" })

과. . . .back at the ranch, Post가 들어 오면 Big Class를 참조하십시오.

 public ActionResult ContactNewspaper(teamBoards teamboards)

모델이 반환 한 내용을 활용합니다.

string yourVariable = teamboards.Team.yourField;

아마도 클래스에 DataAnnotation Validation 항목이있을 것이고 아마도 저장 / 편집 블록의 맨 위에 if (ModelState.IsValid)를 넣을 것입니다. . .


4

사실 두 개 이상의 모델을 둘 다 포함하는 클래스로 래핑하지 않고 하나의 뷰에서 사용하는 방법이 있습니다.

Employee를 예제 모델로 사용 :

@model Employee

실제로 취급됩니다.

@{ var Model = ViewBag.model as Employee; }

따라서 View (employee) 메서드는 모델을 ViewBag로 설정하고 ViewEngine이이를 캐스팅합니다.

즉,

ViewBag.departments = GetListOfDepartments();
    return View(employee);

다음과 같이 사용할 수 있습니다.

            @model  Employee
        @{
                var DepartmentModel = ViewBag.departments as List<Department>;
        }

기본적으로 ViewBag에있는 모든 것을 "모델"로 사용할 수 있습니다. 그래도 작동하는 방식이기 때문입니다. 이것이 건축 적으로 이상적이라고 말하는 것은 아니지만 가능합니다.


3

필요한 모든 정보가 포함 된 단일 뷰 모델을 생성합니다. 일반적으로 모든 뷰에 대해 모델을 생성하여 모든 뷰를 구체적으로 지정하거나 상위 모델을 만들고 상속 할 수 있습니다. 또는 두 뷰를 모두 포함하는 모델을 만드십시오.

개인적으로 나는 그것들을 하나의 모델에 추가 할 것이지만 그것이 내가하는 방식입니다.

public class xViewModel
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}

@model project.Models.Home.xViewModel

@using(Html.BeginForm())
{
    @Html.EditorFor(x => x.PersonID)
    @Html.EditorFor(x => x.PersonName)
    @Html.EditorFor(x => x.OrderID)
    @Html.EditorFor(x => x.TotalSum)
}

1

프레젠테이션 패턴을 사용할 수 있습니다. http://martinfowler.com/eaaDev/PresentationModel.html을 .

이 프레젠테이션 "View"모델은 Person과 Order를 모두 포함 할 수 있으며,이 새로운
클래스는 뷰가 참조하는 모델이 될 수 있습니다.


1
프리젠 테이션 모델은 실제로 필요한 데이터를 포함해야하며 이는 Person 및 Order에서 비롯 될 수 있습니다. 실제로 Person 또는 Order 도메인 개체를 포함해서는 안됩니다. 보기는 기본 도메인에서 디스플레이를 분리합니다.
Fenton

0

언급되지 않은 또 다른 방법은 표시하려는 모든 데이터를 사용하여 MSSQL에서 뷰를 만드는 것입니다. 그런 다음 LINQ to SQL 또는 무엇이든 사용하여 매핑하십시오. 컨트롤러에서보기로 되돌립니다. 끝난.


0

하나의 뷰에서 두 개의 모델을 선언 할 수 없습니다 . Html.Action("Person", "[YourController]")&를 사용해보십시오 Html.Action("Order", "[YourController]").

행운을 빕니다.


이것은 무엇을합니까?
johnny

0

asp.net의 한 뷰 모델 외에도 여러 부분 뷰를 만들고 모든 뷰에 다른 모델 뷰를 할당 할 수 있습니다. 예를 들면 다음과 같습니다.

   @{
        Layout = null;
    }

    @model Person;

    <input type="text" asp-for="PersonID" />
    <input type="text" asp-for="PersonName" />

주문 모델에 대한 또 다른 부분보기 모델

    @{
        Layout = null;
     }

    @model Order;

    <input type="text" asp-for="OrderID" />
    <input type="text" asp-for="TotalSum" />

그런 다음 기본보기에서 부분보기를 모두로드하십시오.

<partial name="PersonPartialView" />
<partial name="OrderPartialView" />

-1

도움이 되셨기를 바랍니다 !!

나는 ViewBag For Project 및 Model for task를 사용하므로 이런 식으로 단일 뷰에서 두 모델을 사용하고 컨트롤러에서 viewbag의 값 또는 데이터를 정의했습니다.

List<tblproject> Plist = new List<tblproject>();
            Plist = ps.getmanagerproject(c, id);

            ViewBag.projectList = Plist.Select(x => new SelectListItem
            {
                Value = x.ProjectId.ToString(),
                Text = x.Title
            });

보기에서 tbltask와 projectlist는 내 두 개의 diff 모델입니다.

@ {

IEnumerable<SelectListItem> plist = ViewBag.projectList;

} @model 목록

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.