2017-04-05 53 views
1

我目前正在開發一個系統,其中依賴於來自不同網站設​​置的請求來自哪個域需要加載(例如默認語言ID),然後在應用程序的其餘部分中使用該系統。這些設置存儲在類WebsiteSettings中,需要時將其注入應用程序的其餘部分。IHttpContextAccessor null注入後

我嘗試的第一個選項是註冊服務在我ConfigureServices方法做這個訪問HttpContext

public void ConfigureServices(IServiceCollection services) 
{ 
    //Register other services 

    services.TryAddScoped<IHttpContextAccessor, HttpContextAccessor>(); 
    services.TryAddScoped<WebsiteSettingsFiller>(); 
    services.TryAddScoped(typeof(WebsiteSettings), s => 
    { 
     var settingFiller = s.GetService<WebsiteSettingsFiller>(); 
     return settingFiller.Create(); 
    }); 
} 

接下來,我WebsiteSettingsFiller服務,我注入我需要的IHttpContextAccessor和其他一些服務加載網站設置。

public class WebsiteSettingsFiller 
{ 
    protected readonly IRepository Database; 
    private readonly IHttpContextAccessor _accessor; 
    private readonly StartupSitePropertyService _sitePropertyService; 
    private IQueryable<Site> AllSites => Database.All<Site>(); 
    private IQueryable<SiteLanguage> AllSiteLanguages => Database.All<SiteLanguage>(); 

    public WebsiteSettingsFiller(IRepository db, StartupSitePropertyService siteProperties, IHttpContextAccessor accessor) 
    { 
     Database = db; 
     _accessor = accessor; 
     _sitePropertyService = siteProperties; 
    } 

    public WebsiteSettings Create() 
    { 
     var domain = _accessor.HttpContext.Request.Host.Host; //null exception on this line 
#if DEBUG 
     domain = "www.somewebsite.com"; 
#endif 
     var config = GetConfigByDomain(domain); 
     return config; 
    } 

    private WebsiteSettings GetConfigByDomain(string domain) 
    { 
     var site = AllSites.OrderByDescending(s => s.Created).FirstOrDefault(t => t.Host == domain); 
     if (site == null) return null; 
     var languages = AllSiteLanguages.Where(sl => sl.SiteId == site.Id).ToList(); 
     //get more variables 
     return new WebsiteSettings 
     { 
      /* Set variables */ 
     } 
    } 
} 

例注射WebsiteSettings

public class RouteService : BaseService 
{ 
    private IDictionary<int, string> _routeLanguages = null; 
    private readonly WebsiteRedisService _websiteRedisService; 

    public RouteService(IRepository db, 
     WebsiteSettings settings, 
     WebsiteRedisService websiteRedisService) 
     : base(db, settings) 
    { 
     _websiteRedisService = websiteRedisService; 
    } 

    public async Task<IDictionary<int, string>> RouteLanguagesAsync() 
    { 
     return _routeLanguages ?? 
       (_routeLanguages = await _websiteRedisService.SiteLanguagesToAsync(Settings.SiteId)); 
    } 
} 

可悲的是,無論我怎麼努力的HttpContext引用總是空。有誰知道我可以嘗試解決這個問題嗎?或者我只是以錯誤的方式來解決這個問題?任何建議,非常感謝!

+0

嘗試註冊爲單:'services.TryAddSingleton ();' – Evk

+0

可悲沒有解決的問題。另外我認爲它需要'TryAddScoped',因爲'HttpContext'訪問器每個請求都會改變,對吧? – nbokmans

+0

在這[issue](https://github.com/aspnet/Hosting/issues/793)中聲稱HttpContextAccessor應該被註冊爲singleton,否則它將無法工作(因爲它的內部實現)。 – Evk

回答

1

IHttpContextAccessor應該作爲Singleton注入。

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 
} 

在你WebsiteSettingsFiller,你可以在構造函數中HttpContext並分配到一個HttpContext場。

public class WebsiteSettingsFiller 
{ 
    //private readonly IHttpContextAccessor _accessor; 
    private readonly HttpContext _context; 

    public WebsiteSettingsFiller(IHttpContextAccessor accessor) 
    { 
     //_accessor = accessor; 
     _context = accessor.HttpContext; 
    } 
} 
+0

這正是我正在做的和不工作 – nbokmans

+0

添加爲單身人士爲我工作... – user1447718