Hai mô hình trong một chế độ xem trong ASP MVC 3


91

Tôi có 2 mô hình:

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; }
}

Tôi muốn chỉnh sửa các đối tượng của CẢ HAI lớp trong chế độ xem SINGLE, vì vậy tôi cần một cái gì đó như:

@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)
}

Tất nhiên, điều này không hoạt động: Chỉ một câu lệnh 'model' được phép trong tệp .cshtml. Có thể có một số cách giải quyết?


1
Câu trả lời của tôi có giúp được gì cho bạn không?
Andrew

tôi được sử dụng ViewBagvới từng theo quan điểm làm việc cho tôi, kiểm tra này để biết nhiều tùy chọn, lưu ít thời gian cho tôi thay vì tạo ra một mô hình xem hoặc một phần nhìn
shaijut

Câu trả lời:


118

Tạo một mô hình dạng xem chính có chứa cả hai mô hình.

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

Bằng cách này, bạn có thể thêm các mô hình bổ sung vào một ngày sau đó với nỗ lực rất ít.


2
Khi sử dụng giải pháp này, xin lưu ý rằng các thay đổi đối với Model1 hoặc Model2 có thể ảnh hưởng đến MainPageModel của bạn. Ngoài ra, chúng chính chứa nhiều dữ liệu hơn chế độ xem thực sự cần. Nếu MainPage của bạn là sự kết hợp của những thứ đã có trong các bộ điều khiển khác, việc chuyển từ RenderPartial sang RenderAction sẽ cho phép bạn giữ mọi thứ được tách biệt gọn gàng. Cân nhắc đọc Quy luật Demeter: en.wikipedia.org/wiki/Law_of_Demeter
Fenton

1
@Andi - Tôi đã tạo Mô hình như bạn đề xuất ở trên. Nhưng khi tôi nhấp chuột phải vào bộ điều khiển và cố gắng tạo bộ điều khiển Crud, nó không hoạt động? Bất kỳ đề xuất? Làm cách nào tôi có thể tạo bộ điều khiển crud với chế độ xem tự động cho Mô hình trên?
NoviceMe,

2
Trong tất cả các cách tiếp cận tôi đã thấy để giải quyết vấn đề này, đây là cách phù hợp nhất với tôi. Đây là giải pháp đơn giản nhất có hiệu quả.
Ciaran Gallagher

4
Sự xúc động khi bạn tự hỏi bản thân "Tại sao tôi không nghĩ về điều đó trước đây?" Giải pháp tuyệt vời
Rafael AMS

1
@Andi Làm cách nào để hiển thị các phương thức của mô hình tương ứng trong bộ điều khiển?
Volatil3

53

Để sử dụng tuple, bạn cần làm như sau, trong giao diện thay đổi mô hình thành:

@model Tuple<Person,Order>

để sử dụng các phương thức @html, bạn cần thực hiện như sau:

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

hoặc là

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

Item1 chỉ ra tham số đầu tiên được truyền cho phương thức Tuple và bạn có thể sử dụng Item2 để truy cập mô hình thứ hai, v.v.

trong bộ điều khiển của bạn, bạn cần tạo một biến kiểu Tuple và sau đó chuyển nó vào dạng xem:

    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);
    }

Một ví dụ khác: Nhiều mô hình trong một chế độ xem


1
Không bao giờ sử dụng một Tupletrong trường hợp này - OP đang muốn chỉnh sửa dữ liệu, và Tuplekhông có constructor mặc định để mô hình không thể bị ràng buộc khi biểu mẫu được gửi

Không bao giờ nói không bao giờ. Đó là một chút mạnh mẽ ở đây.
johnny

47

Một tùy chọn khác không cần tạo Mô hình tùy chỉnh là sử dụng Tuple <> .

@model Tuple<Person,Order>

Theo câu trả lời của Andi, nó không sạch bằng việc tạo một lớp mới chứa cả hai, nhưng nó khả thi.


trong mvc 3 nó báo lỗi Chỉ cho phép một câu lệnh 'model' trong một tệp. Bất kỳ ý tưởng làm thế nào để giải quyết nó?
GibboK

1
@GibboK - Tôi đang sử dụng nó trong MVC3. Hãy chắc chắn rằng bạn không có hai @modeldòng riêng biệt ?
Bobson

3
Bạn có thể nhận các thuộc tính của từng Model với: @Model.Item1.Property@Model.Item2.Propertycho PersonOrdertương ứng
user2019515

1
Tôi đã sử dụng Tuple trong Chế độ xem của mình. Tuy nhiên, tôi không thể lấy các giá trị mô hình trong bộ điều khiển của mình. Tuy nhiên, trong khi tôi sử dụng mô hình dạng xem Parent như @Andi đề xuất, tôi đã nhận được các giá trị mô hình trong bộ điều khiển của mình.
Naren

1
@StephenMuecke - Hừm. Tôi chưa bao giờ nghĩ đến điều đó, nhưng bạn nói đúng. Một lý do khác khiến câu trả lời của Andrew là câu trả lời có mục đích chung tốt hơn. Khi bạn sử dụng sản phẩm thay thế trọng lượng nhẹ (như thế này), bạn sẽ từ bỏ chức năng.
Bobson

10

Nếu bạn là người thích có các mô hình rất phẳng, chỉ để hỗ trợ chế độ xem, bạn nên tạo một mô hình cụ thể cho chế độ xem cụ thể này ...

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

Nhiều người sử dụng AutoMapper để ánh xạ từ các đối tượng trong miền sang chế độ xem phẳng của họ.

Ý tưởng của mô hình khung nhìn là nó chỉ hỗ trợ khung nhìn - không có gì khác. Bạn có một cái cho mỗi chế độ xem để đảm bảo rằng nó chỉ chứa những gì cần thiết cho chế độ xem đó - không chứa vô số thuộc tính mà bạn muốn cho các chế độ xem khác.


5

ok, mọi người đều có lý và tôi đã lấy tất cả các mảnh và đặt chúng ở đây để giúp những người mới như tôi cần lời giải thích từ đầu đến cuối.

Bạn tạo ra một lớp học lớn có 2 lớp, theo câu trả lời của @ Andrew.

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

Sau đó, trong bộ điều khiển của bạn, bạn điền vào 2 mô hình. Đôi khi bạn chỉ cần điền một. Sau đó, ngược lại, bạn tham chiếu mô hình lớn và nó sẽ đưa 2 bên trong cùng với nó vào Chế độ xem.

            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);

Ở đầu Chế độ xem

@model yourNamespace.Models.teamBoards

Sau đó tải đầu vào của bạn hoặc hiển thị tham chiếu nội dung Mô hình lớn:

 @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" })

Và. . . . quay lại trang trại, khi Bài đăng đến, hãy tham khảo Big Class:

 public ActionResult ContactNewspaper(teamBoards teamboards)

và tận dụng những gì (các) mô hình đã trả về:

string yourVariable = teamboards.Team.yourField;

Có thể có một số công cụ DataAnnotation Validation trong lớp và có thể đặt if (ModelState.IsValid) ở đầu khối lưu / chỉnh sửa. . .


4

Trên thực tế, có một cách để sử dụng hai hoặc nhiều mô hình trên một khung nhìn mà không cần gói chúng trong một lớp chứa cả hai.

Sử dụng Nhân viên làm mẫu ví dụ:

@model Employee

Thực sự được đối xử như thế nào.

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

Vì vậy, phương thức View (nhân viên) đang đặt mô hình của bạn thành ViewBag và sau đó ViewEngine đang truyền nó.

Điều này có nghĩa rằng,

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

Có thể được sử dụng như,

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

Về cơ bản, bạn có thể sử dụng bất kỳ thứ gì có trong ViewBag của mình làm "Model" vì đó là cách nó hoạt động. Tôi không nói rằng đây là lý tưởng về mặt kiến ​​trúc, nhưng nó hoàn toàn có thể.


3

Chỉ cần tạo một Mô hình chế độ xem duy nhất với tất cả thông tin cần thiết trong đó, những gì tôi làm là tạo một mô hình cho mọi chế độ xem để tôi có thể cụ thể hóa mọi chế độ xem, hoặc tạo mô hình mẹ và kế thừa nó. HOẶC tạo một mô hình bao gồm cả hai chế độ xem.

Cá nhân tôi sẽ chỉ thêm chúng vào một mô hình nhưng đó là cách tôi làm điều đó:

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

Bạn có thể sử dụng mẫu trình bày http://martinfowler.com/eaaDev/PresentationModel.html

Mô hình "Chế độ xem" bản trình bày này có thể chứa cả Người và Đơn hàng,
lớp mới này có thể là mô hình tham chiếu chế độ xem của bạn.


1
Mô hình trình bày thực sự phải chứa dữ liệu được yêu cầu, dữ liệu này có thể bắt nguồn từ Người và Đơn hàng. Nó không thực sự chứa các đối tượng miền Person hoặc Order. Chế độ xem tách màn hình khỏi miền bên dưới.
Fenton

0

Một cách khác không bao giờ được nói đến là Tạo một khung nhìn trong MSSQL với tất cả dữ liệu bạn muốn trình bày. Sau đó, sử dụng LINQ to SQL hoặc bất cứ thứ gì để ánh xạ nó. Trong bộ điều khiển của bạn đưa nó trở lại dạng xem. Làm xong.


0

bạn không thể khai báo hai mô hình trên một chế độ xem, hãy thử sử dụng Html.Action("Person", "[YourController]")&Html.Action("Order", "[YourController]") .

Chúc may mắn.


Điều này làm gì?
johnny

0

Bên cạnh một mô hình dạng xem trong asp.net, bạn cũng có thể tạo nhiều dạng xem từng phần và chỉ định dạng xem mô hình khác nhau cho mọi dạng xem, ví dụ:

   @{
        Layout = null;
    }

    @model Person;

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

thì mô hình xem một phần khác cho mô hình đặt hàng

    @{
        Layout = null;
     }

    @model Order;

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

sau đó trong chế độ xem chính của bạn tải cả chế độ xem từng phần bằng

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

-1

Tôi hy vọng bạn thấy nó hữu ích !!

tôi sử dụng ViewBag cho Dự án và Mô hình cho tác vụ vì vậy theo cách này, tôi đang sử dụng hai mô hình trong chế độ xem đơn và trong bộ điều khiển, tôi đã xác định giá trị hoặc dữ liệu của 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
            });

và theo quan điểm tbltask và projectlist là hai mô hình khác nhau của tôi

@ {

IEnumerable<SelectListItem> plist = ViewBag.projectList;

} Danh sách @ model

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.