2013-08-20 37 views
6

Tôi đã có ứng dụng Web.Forms kế thừa được viết lại một phần cho MVC. Phần MVC sử dụng autofac như một container tiêm phụ thuộc.Autofac, MVC (với ActionFilters), Web.Forms - xung đột độ phân giải phụ thuộc

MVC phần có bộ lọc tùy chỉnh định nghĩa:

public class CustomActionFilter : ActionFilterAttribute 
{ 
    protected ILogger Logger { get; set; } 
    public CustomActionFilter(ILogger logger) { Logger = logger; } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     Logger.Log("OnActionExecuting"); 
    } 
} 

Nó hoạt động tốt khi Web.Forms hội nhập bị vô hiệu hóa trong web.config. Hovewer, khi tôi cố gắng sử dụng tích hợp autofac Web.Forms, tôi đã có NullReferenceException liên quan đến AutofacFilterProvider ở đâu đó trong autofac internals (stack trace).

Lưu ý rằng CustomActionFilter được đăng ký như lọc toàn cầu, do đó nó được đăng ký với autofac:

public class FilterConfig 
{ 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new HandleErrorAttribute()); 
     filters.Add(DependencyResolver.Current.GetService<CustomActionFilter>()); 
    } 
} 

Tôi đã thử:

  1. sử dụng container riêng biệt cho MVC và Web.Forms - cùng kết quả
  2. Sử dụng tiêm bất động sản thay vì xây dựng - cùng kết quả
  3. Rõ ràng kích hoạt độ phân giải phụ thuộc vào các trang web.forms (như this) - làm việc

Vì vậy, câu hỏi đặt ra là, có cách nào để cung cấp độ phân giải phụ thuộc hậu trường cho cả phần MVC và web.forms. Tôi mới sử dụng autofac và phần nào mới cho các container tiêm phụ thuộc nói chung, vì vậy tôi chỉ có thể bỏ lỡ một cái gì đó hiển nhiên.

Cập nhật: lỗi không có liên quan gì với bộ lọc tùy chỉnh. Nếu tôi loại bỏ tất cả các tham chiếu đến các bộ lọc tùy chỉnh thì hành vi lỗi vẫn giống nhau, ngay cả theo dõi ngăn xếp.

+0

Điều gì xảy ra nếu bạn nhận xét 'ContainerDisposalModule' và sau đó bạn có thể mở lại' PropertyInjectionModule' và 'AttributedInjectionModule'? Không được cần đến 'ContainerDisposalModule' vì Autofac.MVC bao gồm một' RequestLifetimeHttpModule' mới để phân bổ Lifetimscope được tạo ra trong yêu cầu ... – nemesv

+0

@nemesv cùng một kết quả. – J0HN

+0

OK, bây giờ tôi thấy vấn đề là gì ... bạn sẽ có các dịch vụ đã đăng ký với 'InstancePerHttpRequest' chưa? – nemesv

Trả lời

6

Thực ra có hai lỗi? trong Autofac mà gây ra hành vi này:

Bug # 1: Như tác dụng phụ của việc sửa chữa của Issue 351 các AutofacDependencyResolver cần phải đăng ký tại Yêu cầu được tạo ràng buộc LifeTimeScope s. Việc tích hợp MVC thực hiện điều này nhưng sự tích hợp Winforms của khóa học thì không.

Lỗi? # 2: Cả RequestLifetimeScopeProviderContainerProvider các cửa hàng tạo ILifetimeScope với phím cùng HttpContext.Current.Items:

static ILifetimeScope LifetimeScope 
{ 
    get { return (ILifetimeScope)HttpContext.Current.Items[typeof(ILifetimeScope)]; } 
    set { HttpContext.Current.Items[typeof(ILifetimeScope)] = value; } 
} 

Vì vậy, có một chút điều kiện chút chủng tộc ở đây vì tùy thuộc vào mô-đun được thực hiện đầu tiên trên WebForms hoặc intergartion MVC ILifetimeScope thắng. Vì vậy, nếu mô-đun WebForms thắng AutofacDependencyResolver sẽ không được đăng ký và bạn sẽ nhận được ngoại lệ không mô tả tốt đẹp.

Fix/workaround:

Nhưng có một cách giải quyết đơn giản: bạn chỉ cần đăng ký AutofacDependencyResolver trong ContainerProviderrequestLifetimeConfiguration vì vậy không có vấn đề mà một chiến thắng (WebForm vs MVC) các AutofacDependencyResolver sẽ luôn đăng ký :

var autofacDependencyResolver = new AutofacDependencyResolver(container); 
DependencyResolver.SetResolver(autofacDependencyResolver); 
_containerProvider = new ContainerProvider(container, requestContainerBuilder => 
    requestContainerBuilder.RegisterInstance(autofacDependencyResolver) 
    .As<AutofacDependencyResolver>()); 
+0

Làm việc như một sự quyến rũ, cảm ơn bạn rất nhiều. – J0HN

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