2012-03-16 33 views
5

Khi xây dựng mô hình xem trong MVC3 của asp.net, mã sẽ đi đến đâu để khởi tạo các đối tượng của mô hình chế độ xem đó? Tôi đang làm nó chủ yếu trong bộ điều khiển ngay bây giờ, ngoài mã để truy vấn cơ sở dữ liệu. Dưới đây là một ví dụ trong mã:Mã để xây dựng mô hình xem ở đâu?

Xem mẫu:

public class WorkListVM 
{ 
    //list for employees 
    [Display(Name = "Select A Employee")] 
    [Required] 
    public int? EmployeeId { get; set; } 
    public GenericSelectList EmployeeList { get; set; } 
} 

khiển Code:

 //build view model 
     var vm = new WorkListVM(); 

     //build employee list 
     vm.EmployeeList = new GenericSelectList(0,"-- Select Employee --"); 
     var employees = new List<Employee>(); 
     using (var gr = new GenericRepo<Employee>()) 
     { 
      employees = gr.Get().ToList(); 
     } 
     foreach(var employee in employees) 
     { 
      var gl = new GenericListItem(); 
      gl.Id = employee.EmployeeId; 
      gl.DisplayFields = employee.FirstName + " " + employee.LastName; 
      vm.EmployeeList.Values.Add(gl); 
     } 

Generic Chọn Danh sách là một lớp đơn giản để giữ dữ liệu mà đi trong helper @html.dropdownfor 's SelectList. Tôi xây dựng các danh sách lựa chọn này, và cũng xây dựng các cấu hình dữ liệu tương tự cho các mô hình khung nhìn bên trong mã điều khiển. Bộ điều khiển lưu trữ mã này có tổng số 109 dòng mã, do đó, nó không phải là rất lớn hoặc ngoài tầm kiểm soát. Tuy nhiên, tôi luôn luôn phấn đấu để giảm sự thừa và đôi khi mã trong //build employee list kết thúc lên được sao chép dán (ugh, tôi ghét sao chép dán) vào bộ điều khiển khác.

Có nơi nào tốt hơn để có mã này không? Tôi có nên sử dụng mẫu nhà máy để xây dựng dữ liệu cho các danh sách chọn/các đối tượng dữ liệu chế độ xem khác không?

EDIT

Cảm ơn tất cả sự giúp đỡ của bạn. Đây là những gì tôi đã làm. Tôi đã kết thúc thực hiện một phương pháp bên trong chọn lớp danh sách chung rất giống với .ToSelectList (...) được đề xuất bởi Richard và Jesse:

public class GenericSelectList 
{ 
    public List<GenericListItem> Values { get; set; } 
    public int StartValue { get; set; } 
    public string Message { get; set; } 

    public GenericSelectList(int StartValue = 0, string Message = "select") 
    { 
     Values = new List<GenericListItem>(); 
     this.StartValue = StartValue; 
     this.Message = Message; 
    } 

    public void BuildValues<T>(List<T> items, Func<T, int> value, Func<T, string> text) where T : class 
    { 
     this.Values = items.Select(f => new GenericListItem() 
     { 
      Id = value(f), 
      DisplayFields = text(f) 
     }).ToList(); 
    } 
} 
+0

Nếu bạn trả lại chế độ xem của bạn thành chế độ xem, thì mã sẽ nằm trong bộ điều khiển. –

+0

@ 白 ジ ェ ー ム ス - Có, ở cuối phương thức actionresult này là 'return View (vm);'. Chế độ xem được nhập mạnh mẽ '@model WorkListVM'. Một số mã này được sử dụng nhiều lần (trong các bộ điều khiển khác nhau). Nó sẽ không có ý nghĩa để có một nhà máy kết thúc tốt đẹp việc tạo ra các đối tượng viewmodel này để giảm sự dư thừa? –

Trả lời

2

Nếu logic kinh doanh mà đi vào việc tạo ra một mô hình xem là khá phức tạp Tôi thường giải nén nó vào một phương pháp helper mà tôi có thể kiểm tra một cách độc lập của bộ điều khiển.

Tuy nhiên, điều đó sang một bên, việc tạo mô hình chế độ xem của bạn hoàn toàn ổn trong bộ điều khiển. Như đã được lưu ý, cách tạo danh sách lựa chọn của bạn có thể được thực hiện đơn giản hơn nhiều (chưa kể đến việc tái sử dụng).

Đây là một phần mở rộng ToSelectList của IEnumerable cùng với một ví dụ về việc sử dụng:

public static List<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> value, Func<T, string> text, string defaultOption) 
{ 
    var items = enumerable.Select(f => new SelectListItem() 
              { 
               Text = text(f) , 
               Value = value(f) 
              }).ToList(); 

    if (!string.IsNullOrEmpty(defaultOption)) 
    { 
        items.Insert(0, new SelectListItem() 
         { 
          Text = defaultOption, 
          Value = string.Empty 
         }); 
    } 

    return items; 
} 

Trong mô hình quan điểm của bạn, bạn có thể thêm một tài sản như sau:

IEnumerable<SelectListItem> Employees { get; set; } 

Trong vòng điều khiển của bạn (i' m giả định rằng repo của bạn đang trả về IEnumberable):

var employees = new IEnumerable<Employee>(); 
using (var gr = new GenericRepo<Employee>()) 
{ 
    employees = gr.Get(); 
} 

vm.Employees = employees.ToSelectList(x=>x.FirstName + " " + x.LastName, x=>x.Id, "-- Select Employee --") 

Sau đó thiết lập danh sách thả xuống của bạn trong chế độ xem sẽ trông giống như sau:

@Html.DropDownListFor(model => model.EmployeeId, Model.employees) 
+0

+1 - Tâm trí tuyệt vời nghĩ như nhau;) Và bạn đã lưu cho tôi bản dịch! – RichardW1001

+0

Phần mở rộng rất tốt, cảm ơn bạn đã nhập chủ đề này :) –

+0

@Jesse - Ý tưởng của bạn về tiện ích mở rộng là tốt, nhưng tôi đã quyết định biến nó thành một phương pháp bên trong lớp tôi sử dụng cho các danh sách được chọn. Xem bản chỉnh sửa của tôi để triển khai. Cảm ơn một lần nữa! –

2

Nếu mục tiêu của bạn là để tránh mã dư thừa, bạn nên giải nén phổ biến các bộ phận vào các phương thức trợ giúp. Ở dạng đơn giản nhất, bạn có thể sử dụng các phương thức tĩnh cho việc này.

Mô hình chế độ xem tòa nhà trong bộ điều khiển thường là phương pháp phù hợp, ngoại trừ nếu có lý do đặc biệt chống lại nó.

Bạn có thể cấu trúc mã theo bất kỳ cách nào bạn muốn. Sử dụng các kỹ thuật tiêu chuẩn để đối phó với sự phức tạp như phương pháp trợ giúp và trừu tượng hóa (ít). Không cần phải phức tạp khi đơn giản là đủ.

2

1 - Bạn có thể thêm phương thức tiện ích mở rộng vào IEnumerable<Employee> hoặc IQueryable<Employee> trả về số GenericSelectList của bạn. Ưu điểm - bạn có thể sử dụng lại đối với bất kỳ bộ sưu tập nào của nhân viên, tức là danh sách được lọc và cú pháp gọi khá đẹp; bạn có thể tùy chỉnh cách danh sách lựa chọn được hình thành trên cơ sở từng trường hợp. Nhược điểm - bạn sẽ phải viết một trong những phương pháp này cho từng loại.

2 - Bạn có thể thay đổi phương thức mở rộng đó để làm việc chung, hoạt động với IEnumerable<T> và tạo ra GenericSetList dựa trên đầu vào Expression. Ưu điểm - Phương pháp của bạn bây giờ thực sự là chung chung, tức là viết một lần và tái sử dụng. Bạn có thể làm điều này theo cách mà nó kết hợp với 1 để hàm 1-mỗi-lớp của bạn sử dụng chung để lưu trùng lặp. Nhược điểm - giả định sự thoải mái trong việc sử dụng các biểu thức và những thứ tương tự.

3 - Bạn có thể có phương thức nhà máy trả về Chế độ xem.

Những điều này cũng có thể hoạt động kết hợp, và sẽ giúp loại bỏ mã sao chép/dán và thúc đẩy sử dụng lại và thử nghiệm.

Chỉnh sửa - dưới đây là một cách không có. 2 có thể được thực hiện (trong VB nhưng dịch sang C# là tầm thường).Sau đó tôi sẽ thêm quá tải cho các hoán vị hữu ích của đầu vào.

Imports System.Runtime.CompilerServices 
Imports System.Linq.Expressions 

Module IQueryableExtensions 

    <Extension()> 
    Public Function ToSelectList(Of T)(source As IEnumerable(Of T), nameExpression As Expression(Of Func(Of T, String)), valueExpression As Expression(Of Func(Of T, String)), selectedExpression As Expression(Of Func(Of T, Boolean)), additionalItems As IEnumerable(Of SelectListItem)) As IEnumerable(Of SelectListItem) 
     Return additionalItems.Union(
      source.Select(Function(x) New SelectListItem With { 
           .Text = nameExpression.Compile.Invoke(x), 
           .Value = valueExpression.Compile.Invoke(x), 
           .Selected = selectedExpression.Compile.Invoke(x) 
          } 
        ) 
       ) 
    End Function 

End Module 

sử dụng mẫu:

Dim People As New List(Of Person) From {New Person With {.Name = "Richard", .ID = 1}} 

    Dim sl = People.ToSelectList(Function(p) p.Name, 
           Function(p) p.ID, 
           Function(p) p.ID = 1, 
           {New SelectListItem With {.Value = 0, 
                  .Text = "Please Select A Person"}}) 
+0

Tôi có thể làm # 2, trong đó tôi sẽ thêm một phản ứng chung cho việc tạo danh sách lựa chọn. Tuy nhiên, nó sẽ đòi hỏi sự phản chiếu. Nó sẽ là không khôn ngoan để sử dụng sự phản chiếu trong kho lưu trữ? –

+0

Bạn đang nói phản chiếu vì bạn muốn đưa tên lớp? Có những cách khác làm tròn điều đó, cho tôi một giây và tôi sẽ gửi một mẫu. – RichardW1001

+0

@TravisJ - ở đó bạn đi - một triển khai có thể có không có sự phản ánh. – RichardW1001

1

Tôi không biết nếu điều này là đúng cách, nhưng tôi sử dụng nó và nó giúp tôi giữ quyền kiểm soát tất cả mọi thứ.

bộ điều khiển trong mắt của tôi thực hiện những việc như phiên cập nhật, cookie và sau đó trả về chế độ xem. Tôi không bao giờ sử dụng nó để phân loại bất kỳ dữ liệu hoặc tạo ra các đối tượng để gửi đến xem.

(tôi có thể ăn gian nếu một của nó một lót: p)

tất cả những thứ mà tôi thêm vào lớp trợ giúp. Mỗi khi tôi cảm thấy một bản sao và dán đi vào tôi tạo ra một phương pháp mới trong helper của tôi và gọi thay vào đó.

cộng với, bạn sẽ có được cảm giác tốt đẹp khi được 3 ngày sau đó bạn cần phải sử dụng phương pháp và tất cả những điều đó đang chờ đợi.

Martyn

+1

người đàn ông .. Tôi gõ quá chậm, 2 câu trả lời trong khi tôi đang khai thác! – SmithMart

+0

Vì vậy, có lẽ tôi chỉ nên thực hiện một phương pháp trợ giúp chung bằng cách sử dụng sự phản chiếu để quản lý việc tạo ra các danh sách này ... –

Các vấn đề liên quan