2012-08-22 26 views
15

Có thể có api web chung chung để hỗ trợ bất kỳ mô hình nào trong dự án của bạn không?Bộ điều khiển Api Web chung để hỗ trợ bất kỳ mô hình nào

class BaseApiController<T> :ApiController 
{ 
    private IRepository<T> _repository; 

    // inject repository 

    public virtual IEnumerable<T> GetAll() 
    { 
     return _repository.GetAll(); 
    } 

    public virtual T Get(int id) 
    { 
     return _repositry.Get(id); 
    } 

    public virtual void Post(T item) 
    { 
     _repository.Save(item); 
    } 
    // etc... 
} 

class FooApiController : BaseApiController<Foo> 
{ 
    //.. 

} 

class BarApiController : BaseApiController<Bar> 
{ 
    //.. 
} 

Đây có phải là cách tiếp cận tốt không?

Sau khi tất cả, tôi chỉ lặp lại các phương pháp CRUD? Tôi có thể sử dụng lớp cơ sở này để thực hiện công việc cho tôi không?

OK? bạn sẽ làm điều này? bất kỳ ý tưởng tốt hơn?

+0

Xin chào, tôi biết đây là câu hỏi cũ, nhưng bạn có thể giải thích cách bạn quản lý để gọi các phương pháp hành động chung của mình không? Nó không giống như bạn có thể thực hiện điều này chỉ với quy tắc định tuyến. Tôi sẽ đánh giá cao về nó. – Brett

Trả lời

22

Tôi đã làm điều này cho một dự án nhỏ để có được một cái gì đó và chạy để demo cho khách hàng. Một khi tôi đã đi vào chi tiết cụ thể của các quy tắc kinh doanh, xác nhận và cân nhắc khác, tôi đã phải ghi đè lên các phương thức CRUD từ lớp cơ sở của tôi để nó không được triển khai như là một triển khai dài hạn.

Tôi chạy vào vấn đề với định tuyến, bởi vì không phải tất cả mọi thứ đã sử dụng một ID cùng loại (Tôi đã làm việc với một hệ thống hiện có). Một số bảng có int khóa chính, một số có strings và các khóa khác có guids.

Tôi cũng đã gặp sự cố với điều đó. Cuối cùng, trong khi nó có vẻ trơn tru khi tôi lần đầu tiên làm điều đó, thực sự sử dụng nó trong một thực tế thế giới thực hiện đã được chứng minh là một vấn đề khác nhau và đã không đưa tôi đi xa hơn ở tất cả.

+6

cũng bạn có thể sử dụng một giao diện gọi nó 'IIdentifier ' để đại diện cho loại khác nhau của id s. – DarthVader

+0

Đúng, nhưng trong tầm nhìn tôi vẫn không nghĩ rằng tôi được hưởng lợi từ việc cố gắng tái cấu trúc lại các hoạt động CRUD thành một bộ điều khiển chung. Nó gây ra quá nhiều đau đầu sau này trong quá trình phát triển. –

+0

Nếu bạn là greenfield, không có lý do tại sao bạn không nên có tất cả "Id" cùng loại .. – LastTribunal

5

Chắc chắn là có thể. Tôi chưa bao giờ có lý do để làm điều đó trước đây, nhưng nếu nó hoạt động cho tình huống của bạn, nó sẽ tốt.

Nếu tất cả các mô hình của bạn có thể được lưu và truy xuất theo cùng một cách chính xác, có lẽ chúng chỉ nên ở trong cùng một bộ điều khiển thay vì?

+0

tại sao nó không hoạt động? về cơ bản phần lớn thời gian, tất cả những gì chúng ta làm là sử dụng các hoạt động tương tự cho tất cả các mô hình miền và lặp lại chúng nhiều lần. – DarthVader

+1

Bạn hỏi nếu có thể, vì vậy tôi trả lời rằng :) Phải thừa nhận rằng tôi nghĩ rằng tôi đã thiếu phần còn lại của câu hỏi, tôi có thể chỉ cần xóa câu trả lời của tôi ... – eouw0o83hf

+0

tôi sẽ cung cấp cho bạn +1 để không xóa câu trả lời của bạn :) – DarthVader

0

Hoàn toàn có thể như đã nói trong câu trả lời trước. Đây là cách tiếp cận tốt và kiến ​​trúc tốt chắc chắn. Nhưng tôi không hiểu tại sao bộ điều khiển của bạn không được công khai. Có thể đó là vấn đề của bạn và vì nó mã của bạn không hoạt động?

+0

oh tôi chỉ cần gõ ở đây một cách nhanh chóng. đã không chú ý quá nhiều để truy cập các công cụ sửa đổi. – DarthVader

+0

Vậy các triệu chứng không hoạt động là gì? –

+0

người đã nói không hoạt động? tôi hỏi nếu nó khả thi hay thiết kế tốt/ – DarthVader

1

Không có gì sai với điều này miễn là bạn xử lý tất cả việc nâng hạng nặng trong kho của bạn. Bạn có thể muốn bọc/xử lý các ngoại lệ mô hình trong bộ điều khiển cơ sở của bạn. Tôi thực sự đang làm một cái gì đó tương tự cho một dự án lớn nơi người dùng có thể xác định thực thể và API của chính họ - nghĩa là: một người dùng có thể muốn có người dùng và tài khoản trong khi người dùng khác có thể muốn theo dõi xe ô tô và bất kỳ thứ gì khác. Tất cả chúng đều sử dụng cùng một bộ điều khiển bên trong, nhưng chúng đều có các điểm cuối riêng của chúng.

Không chắc chắn mã của chúng tôi hữu ích như thế nào vì chúng tôi không sử dụng Generics (mỗi đối tượng được duy trì dưới dạng siêu dữ liệu và thao tác/chuyển qua lại như từ điển JObject) nhưng đây là một số mã để cung cấp cho bạn ý tưởng chúng tôi đang làm và có thể cung cấp thực phẩm cho các tư tưởng:

[POST("{primaryEntity}", RouteName = "PostPrimary")] 
public async Task<HttpResponseMessage> CreatePrimary(string primaryEntity, JObject entity) 
{ 
    // first find out which params are necessary to accept the request based on the entity's mapped metadata type 
    OperationalParams paramsForRequest = GetOperationalParams(primaryEntity, DatasetOperationalEntityIntentIntentType.POST); 

    // map the passed values to the expected params and the intent that is in use 
    IDictionary<string, object> objValues = MapAndValidateProperties(paramsForRequest.EntityModel, paramsForRequest.IntentModel, entity); 

    // get the results back from the service and return the data to the client. 
    QueryResults results = await paramsForRequest.ClientService.CreatePrimaryEntity(paramsForRequest.EntityModel, objValues, entity, paramsForRequest.IntentModel); 
     return HttpResponseMessageFromQueryResults(primaryEntity, results); 

} 
+0

Chúc may mắn :) trông rất phức tạp. tôi sẽ tránh tất cả những điều đó. :) – DarthVader

+1

Đối với những gì bạn đang làm, vâng, nhẹ quá mức cần thiết;). Tuy nhiên, mã ở trên cho phép nhiều tài khoản khách hàng có nhiều ứng dụng trong mỗi tài khoản quản lý nhiều thực thể bằng một bộ điều khiển chung (thực ra chúng tôi đã chia nhỏ bộ điều khiển cho mỗi loại hành động) nên không quá phức tạp khi bạn xem xét vấn đề cần giải quyết . Và nếu chúng ta có thể sử dụng mã ở trên và hỗ trợ hàng ngàn máy khách với thời gian phản hồi dưới 100ms, bạn nên sử dụng;). Dù sao, chỉ cố gắng thể hiện một cách khác để hoàn thành nó như là thức ăn cho sự suy nghĩ. – AlexGad

+0

cool :) chúc may mắn :) – DarthVader

1

Nếu bạn có các lớp học thiết kế thời gian được xác định trước, như một mà được tạo ra từ mô hình EF hoặc Mã Đầu tiên thì đây là quá phức tạp đối với hệ thống của bạn. Điều này là tuyệt vời nếu bạn không có các lớp được xác định trước (như trong dự án của tôi nơi các lớp thực thể dữ liệu được tạo ra tại thời gian chạy).

Giải pháp của tôi (chưa được triển khai chính xác) là tạo IHttpControllerSelector tùy chỉnh, chọn bộ điều khiển chung cho tất cả các yêu cầu, tôi có thể đặt kiểu mô tả bộ điều khiển thành bê tông từ thông số chung chung tùy thuộc vào đường dẫn yêu cầu.

Cũng là một điểm khởi đầu tốt là http://entityrepository.codeplex.com/ (Tôi đã tìm thấy một nơi nào đó ở đây trên stackoverflow)

1

Những gì bạn làm chắc chắn là có thể như những người khác nói. Nhưng đối với phụ thuộc kho lưu trữ, bạn nên sử dụng tiêm phụ thuộc. Bộ điều khiển điển hình của tôi (Api hoặc MVC) sẽ như sau.

public class PatientCategoryApiController : ApiController 
{ 

    private IEntityRepository<PatientCategory, short> m_Repository; 
    public PatientCategoryApiController(IEntityRepository<PatientCategory, short> repository) 
    { 
     if (repository == null) 
      throw new ArgumentNullException("entitiesContext is null"); 

     m_Repository = repository; 
    } 
} 

Đây là mô hình tiêm xây dựng điển hình. Bạn cần phải có một sự hiểu biết âm thanh của DI và các thùng chứa như NInject hoặc Autofac. Nếu bạn không biết DI, thì bạn có một con đường dài phía trước. Nhưng đây là một cách tiếp cận tuyệt vời. Hãy xem cuốn sách này. https://www.manning.com/books/dependency-injection-in-dot-net

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