ASP MVC 3'te tek görünümde iki model


92

2 modelim var:

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

TEK görünümde HER İKİ sınıfın nesnelerini düzenlemek istiyorum, bu nedenle şuna ihtiyacım var:

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

Bu, elbette çalışmaz: Bir .cshtml dosyasında yalnızca bir 'model' ifadesine izin verilir. Bir çözüm var mı?


1
Cevabım size yardımcı oluyor mu?
Andrew

ViewBagGörünümdeki her biri için kullandım , benim için çalıştı, birden fazla seçeneği öğrenmek için bunu kontrol et , bir görünüm modeli veya kısmi görünüm oluşturmak yerine benim için çok az zaman
kazandım

Yanıtlar:


119

Her iki modeli de içeren bir üst öğe görünümü modeli oluşturun.

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

Bu şekilde, daha sonraki bir tarihte minimum çabayla ilave modeller ekleyebilirsiniz.


2
Bu çözümü kullanırken, Model1 veya Model2'de yapılan değişikliklerin MainPageModel'iniz üzerinde çarpma etkisi olabileceğini lütfen unutmayın. Ayrıca, ana görünümün gerçekten ihtiyaç duyduğundan daha fazla veri içerirler. MainPage'iniz zaten diğer denetleyicilerde bulunan şeylerin bir birleşimiyse, RenderPartial'dan RenderAction'a geçiş, her şeyi düzgün bir şekilde ayırmanıza olanak tanır. Demeter Yasasını okumayı düşünün: en.wikipedia.org/wiki/Law_of_Demeter
Fenton

1
@Andi - Yukarıda önerdiğiniz gibi Modeli oluşturdum. Ancak denetleyiciye sağ tıklayıp Crud denetleyicisi oluşturmaya çalıştığımda çalışmıyor mu? Herhangi bir öneri? Yukarıdaki Model için otomatik görünüm ile çamur denetleyicisi nasıl oluşturabilirim?
NoviceMe

2
Bu sorunu çözmek için gördüğüm tüm yaklaşımlar arasında benim için en iyi sonuç veren budur. İşe yarayan en basit çözümdür.
Ciaran Gallagher

4
Kendinize "Bunu Neden Daha Önce Düşünmedim?" Diye sorduğunuz an Harika çözüm
Rafael AMS

1
@Andi Denetleyicide ilgili modelin yöntemlerini nasıl açığa çıkarabilirim?
Volatil3

53

Demeti kullanmak için aşağıdakileri yapmanız gerekir, görünümde modeli şu şekilde değiştirin:

@model Tuple<Person,Order>

@html yöntemlerini kullanmak için aşağıdakileri yapmanız gerekir, yani:

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

veya

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

Öğe1, Tuple yöntemine iletilen ilk parametreyi gösterir ve ikinci modele erişmek için Öğe2'yi kullanabilirsiniz.

denetleyicinizde Tuple türünde bir değişken oluşturmanız ve ardından bunu görünüme aktarmanız gerekir:

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

Başka bir örnek: Bir görünümde birden çok model


1
TupleBu durumda asla a kullanmayın - OP verileri düzenlemek istiyor ve Tuple

Asla asla Deme. Burada biraz güçlü.
johnny

47

Özel bir Model yaratma ihtiyacı duymayan başka bir seçenek de Tuple <> kullanmaktır .

@model Tuple<Person,Order>

Andi'nin cevabına göre, her ikisini de içeren yeni bir sınıf yaratmak kadar temiz değil, ama uygulanabilir.


mvc 3'te hata verir Bir dosyada yalnızca bir 'model' ifadesine izin verilir. Nasıl çözüleceğine dair bir fikrin var mı?
GibboK

1
@GibboK - MVC3'te kullanıyorum. İki ayrı @modelhattınız olmadığından emin misiniz ?
Bobson

3
Her Modelin özelliklerini şununla alabilirsiniz: @Model.Item1.Propertyve @Model.Item2.Propertyiçin Personve Ordersırasıyla
user2019515

1
Görünümümde Tuple kullandım. Ancak, denetleyicimdeki model değerlerini alamıyorum. Ancak, @Andi'nin önerdiği gibi Parent view modelini kullanırken, controller'ımdaki model değerlerini aldım.
Naren

1
@StephenMuecke - Hmm. Bunu hiç düşünmemiştim ama haklısın. Andrew'un cevabının bir başka nedeni de daha genel amaçlı olanıdır. Eğer (bu şekilde) bir hafif alternatif gittiğinizde, do işlevsellik vazgeçmek.
Bobson

10

Çok düz modellerin hayranıysanız, sırf görünümü desteklemek için bu özel görünüme özel bir model oluşturmalısınız ...

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

Birçok kişi, etki alanı nesnelerinden düz görünümlerine eşlemek için AutoMapper'ı kullanır.

Görünüm modeli fikri, sadece görünümü desteklemesidir - başka bir şey değil. Diğer görünümler için istediğiniz birçok özelliği değil, yalnızca o görünüm için gerekli olanı içerdiğinden emin olmak için görünüm başına bir tane var.


5

tamam, herkes mantıklı ve ben tüm parçaları aldım ve baştan sona açıklamaya ihtiyaç duyan benim gibi yeni başlayanlara yardım etmek için buraya koydum.

@ Andrew'un cevabına göre 2 sınıftan oluşan büyük sınıfınızı yaparsınız.

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

Ardından kontrol cihazınızda 2 modeli doldurursunuz. Bazen sadece birini doldurmanız gerekir. Daha sonra dönüşte büyük modeli referans alıyorsunuz ve içindeki 2 modeli de View'e götürüyor.

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

Görünümün üst kısmında

@model yourNamespace.Models.teamBoards

Ardından, girişlerinizi veya ekranlarınızı büyük Model içeriklerine göre yükleyin:

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

Ve. . . . çiftlikte, Posta geldiğinde, Büyük Sınıfa atıfta bulunun:

 public ActionResult ContactNewspaper(teamBoards teamboards)

ve modellerin döndürdüklerinden yararlanın:

string yourVariable = teamboards.Team.yourField;

Muhtemelen sınıfta bazı DataAnnotation Validation öğeleri vardır ve muhtemelen kaydet / düzenle bloğunun en üstüne if (ModelState.IsValid) koyar. . .


4

Aslında, iki veya daha fazla modeli, her ikisini de içeren bir sınıfa sarmadan bir görünümde kullanmanın bir yolu vardır.

Çalışanı örnek model olarak kullanmak:

@model Employee

Aslında gibi tedavi edilir.

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

Dolayısıyla, View (çalışan) yöntemi, modelinizi ViewBag'e ayarlıyor ve ardından ViewEngine onu yayınlıyor.

Bu şu demek,

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

Gibi kullanılabilir,

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

Esasen, ViewBag'inizdeki her şeyi bir "Model" olarak kullanabilirsiniz çünkü zaten böyle çalışır. Bunun mimari olarak ideal olduğunu söylemiyorum, ama mümkün.


3

Sadece içinde gerekli tüm bilgileri içeren tek bir görünüm Modeli oluşturun, normalde yaptığım şey her görünüm için bir model oluşturmaktır, böylece her görünümde spesifik olabilirim, ya o ya da bir üst model oluşturup onu miras alabilirim. VEYA her iki görünümü de içeren bir model yapın.

Şahsen onları tek bir modele eklerdim ama bunu yapıyorum:

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 sunum modelini kullanabilirsiniz.

Bu sunum "Görünüm" modeli hem Kişi hem de Sipariş içerebilir, bu yeni
sınıf görünüm referanslarınızın modeli olabilir.


1
Sunum modeli, bir Kişi ve Siparişten kaynaklanabilecek gerekli verileri aslında içermelidir. Kişi veya Sipariş etki alanı nesnelerini gerçekten içermemelidir. Görünüm, ekranı temel alınan etki alanından ayırır.
Fenton

0

Asla konuşulmayan başka bir yol, sunmak istediğiniz tüm verilerle MSSQL'de bir görünüm oluşturmaktır. Ardından LINQ to SQL veya eşlemek için her neyse kullanın. Denetleyicinizde onu görünüme geri döndürün. Bitti.


0

bir görünümde iki model ilan edemezsiniz, Html.Action("Person", "[YourController]")& kullanmayı deneyin Html.Action("Order", "[YourController]").

İyi şanslar.


Bu ne yapar?
johnny

0

Asp.net'teki bir görünüm modelinin yanı sıra, birden çok kısmi görünüm oluşturabilir ve her görünüme farklı model görünümü atayabilirsiniz, örneğin:

   @{
        Layout = null;
    }

    @model Person;

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

sonra sipariş modeli için başka bir kısmi görünüm Modeli

    @{
        Layout = null;
     }

    @model Order;

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

sonra ana görünümünüzde hem kısmi görünümü hem de

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

-1

Umarım yardımcı bulursunuz !!

ViewBag For Project and Model'i görev için kullanıyorum, bu yüzden bu şekilde iki modeli tek görünümde kullanıyorum ve kontrolörde viewbag'in değerini veya verilerini tanımladım

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

ve görünümde tbltask ve projectlist benim iki farklı modelim

@ {

IEnumerable<SelectListItem> plist = ViewBag.projectList;

} @model Listesi

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.