2013-02-22 13 views
8

Trong MVC, ModelValidatorProvider được khởi tạo và được gọi để xác thực mô hình trên mỗi yêu cầu. Điều này có nghĩa là trong môi trường DI, nó có thể phụ thuộc vào các đối tượng được sắp xếp trong một yêu cầu duy nhất, chẳng hạn như bối cảnh Đơn vị công việc hoặc Cơ sở dữ liệu. Trong API Web, điều này dường như đã được thay đổi đáng kể. Thay vì được instantiated cho mỗi yêu cầu, các ModelValidatorProvider xuất hiện để được sống lâu và instantiated trong khởi động ứng dụng. WebAPI sau đó lưu trữ các kết quả từ ModelValidatorProvider mỗi loại, có nghĩa là ModelValidator không thể thực hiện bất kỳ phụ thuộc nào từ DI.Per-Request DependencyResolver trong API Web

Tôi đang cố gắng triển khai ModelValidator để sử dụng nhà máy sử dụng Công cụ định vị dịch vụ (vui lòng không tự động nhận xét 'chống mẫu'). Điều này sẽ cho phép tôi xây dựng một đối tượng validator nội bộ trong mỗi yêu cầu, có thể lấy các phụ thuộc từ container. Tuy nhiên, tôi không thể giữ được một Người phụ thuộc của Người phụ thuộc hoặc thùng chứa được sắp xếp theo yêu cầu hiện tại từ bên trong số ModelValidator này về cơ bản là phạm vi như một Singleton. Tôi đã cố gắng sử dụng GlobalConfiguration.Configuration.DependencyResolver, nhưng chỉ có lợi nhuận này dịch vụ toàn cầu scoped (từ phạm vi gốc, cũng mentioned here)

Tôi đang làm việc trong Autofac, vì vậy một giải pháp autofac cụ thể sẽ thích hợp (ví dụ như MVC có AutofacDependencyResolver.Current , sử dụng nội bộ DependencyResolver.GetService). Không có sẵn tương đương trong tích hợp WebAPI, có lẽ vì lý do được đề cập ở trên, trong đó toàn cầu DependencyResolver chỉ trả về các dịch vụ toàn cầu.

Lý do tôi đang cố gắng thực hiện điều này (cũng như vì mục đích sử dụng của riêng tôi) là triển khai tích hợp API Web cho FluentValidation, hiện không tồn tại. Đã có hai lần thử cho đến nay, nhưng cả hai đều không xử lý vấn đề Dependency Injection và thay vào đó dẫn đến một ModelValidator tĩnh đơn.

Những điều tôi đã cố gắng cho đến nay:

  • Sử dụng GlobalConfiguration.Configuration.DependencyResolver (trả về các đối tượng từ phạm vi root)
  • Lấy một sự phụ thuộc vào Func<IComponentContext> (luôn luôn trả về bối cảnh gốc)

Trong một câu trả lời đã bị xóa, đề xuất xóa dịch vụ IModelValidatorProvider khỏi cấu hình API Web. Điều này phải được thực hiện bằng cách sử dụng sự phản chiếu vì giao diện và các lớp triển khai được định nghĩa là nội bộ, nhưng nó đã làm cho trình duyệt tính hợp lệ hoạt động tốt hơn (vì ModelValidator được xây dựng theo yêu cầu). Tuy nhiên, có một hit hiệu suất đáng kể để thực hiện nó theo cách này do việc sử dụng sự phản chiếu để kiểm tra các trình duyệt tính hợp lệ trên mô hình và mọi thuộc tính mà nó có, vì vậy tôi không muốn thực hiện tùy chọn này.

Câu trả lời của Filip W gợi ý sử dụng HttpRequestMessage để nhận Phạm vi phụ thuộc, nhưng tôi không tìm thấy bất kỳ thứ gì như HttpRequestMessage.Current. rơi vào vị trí.

Trả lời

3

Để nhận phạm vi phụ thuộc hiện tại, bạn phải sử dụng (bất ngờ, ngạc nhiên :) GetDependencyScope() của số HttpRequestMessage hiện tại (bạn có thể đọc thêm on MSDN) thay vì GlobalConfiguration.

Tôi đã viết blog khoảng Web API per-request dependency scope một thời gian trước - điều đó sẽ hữu ích.

+6

Nghe có vẻ như nó gần với giải pháp hơn, nhưng làm cách nào tôi có thể nhận được HttpRequestMessage? Đây là từ trong một lớp học dài hạn. Googling cho thấy điều này là không thể. – Richard