2016-11-22 54 views
1

源:https://gist.github.com/sniffdk/7600822System.ArgumentNullException:值不能爲空 - 上一把umbraco HttpContext的保存和發佈

下面的代碼是由活動的HTTP請求之外運行,所以我需要模擬的HTTP上下文。

我已經嘲笑了HTTP上下文,像這樣:

public class GetUmbracoServiceMockedHttpContext : IGetUmbracoService 
{ 
    private UmbracoHelper umbracoHelper; 

    public T GetService<T>() 
     where T : IService 
    { 
     UmbracoContext context = UmbracoContext.Current; 

     if (context == null) 
     { 
      var dummyHttpContext = new HttpContextWrapper(new HttpContext(new SimpleWorkerRequest("blah.aspx", "", new StringWriter()))); 
      context = UmbracoContext.EnsureContext(
       dummyHttpContext, 
       ApplicationContext.Current, 
       new WebSecurity(dummyHttpContext, ApplicationContext.Current), 
       UmbracoConfig.For.UmbracoSettings(), 
       UrlProviderResolver.Current.Providers, 
       false); 
     } 

     var serviceTypeProperty = context.Application.Services 
      .GetType() 
      .GetProperties() 
      .SingleOrDefault(x => x.PropertyType == typeof(T)); 

     if (serviceTypeProperty == null) 
     { 
      return default(T); 
     } 

     return (T)serviceTypeProperty 
      .GetValue(context.Application.Services); 
    } 
} 

我注入這IGetUmbracoService service到控制器,並呼籲:

service.GetService<IContentService>().SaveAndPublishWithStatus(item); 

...出現以下錯誤。

System.ArgumentNullException:值不能爲空。參數名: 的HttpContext在System.Web.HttpContextWrapper..ctor(HttpContext的 的HttpContext)在 Umbraco.Web.SingletonHttpContextAccessor.get_Value()在 Umbraco.Web.RequestLifespanMessagesFactory.Get()在 Umbraco.Core.Services.ContentService .SaveAndPublishDo(IContent 內容,的Int32用戶id,布爾raiseEvents)在 Umbraco.Core.Services.ContentService.Umbraco.Core.Services.IContentServiceOperations.SaveAndPublish(IContent 內容,的Int32用戶id,布爾raiseEvents)在 Umbraco.Core.Services .ContentService.SaveAndPublishWithStatus(IContent content,Int32 userId,Boolean raiseEvents)

如何在不使用frowned upon HttpContext.Current = ...的情況下模擬http上下文?


我承擔相關的問題來自:

RequestLifespanMessagesFactory.cs

而這又是調用了這樣一個實現:

SingletonHttpContextAccessor.cs

回答

0

感謝user369142。這是什麼結束了工作:

我還必須確保我沒有提出SaveandPublish調用任何事件...因爲HttpContext期望有消息註冊在上下文中,但我們不嘲笑任何。 ..如果你確定raise事件是錯誤的,它會跳過關心該事件的代碼。

public class CustomSingletonHttpContextAccessor : IHttpContextAccessor 
{ 
    public HttpContextBase Value 
    { 
     get 
     { 
      HttpContext context = HttpContext.Current; 
      if (context == null) 
      { 
       context = new HttpContext(new HttpRequest(null, "http://mockurl.com", null), new HttpResponse(null)); 
      } 

      return new HttpContextWrapper(context); 
     } 
    } 
} 

public class CustomRequestLifespanMessagesFactory : IEventMessagesFactory 
{ 
    private readonly IHttpContextAccessor _httpAccessor; 

    public CustomRequestLifespanMessagesFactory(IHttpContextAccessor httpAccessor) 
    { 
     if (httpAccessor == null) 
     { 
      throw new ArgumentNullException("httpAccessor"); 
     } 

     _httpAccessor = httpAccessor; 
    } 

    public EventMessages Get() 
    { 
     if (_httpAccessor.Value.Items[typeof(CustomRequestLifespanMessagesFactory).Name] == null) 
     { 
      _httpAccessor.Value.Items[typeof(CustomRequestLifespanMessagesFactory).Name] = new EventMessages(); 
     } 

     return (EventMessages)_httpAccessor.Value.Items[typeof(CustomRequestLifespanMessagesFactory).Name]; 
    } 
} 

public class CustomBootManager : WebBootManager 
{ 
    public CustomBootManager(UmbracoApplicationBase umbracoApplication) 
     : base(umbracoApplication) 
    { 
    } 

    protected override ServiceContext CreateServiceContext(DatabaseContext dbContext, IDatabaseFactory dbFactory) 
    { 
     //use a request based messaging factory 
     var evtMsgs = new CustomRequestLifespanMessagesFactory(new CustomSingletonHttpContextAccessor()); 

     return new ServiceContext(
      new RepositoryFactory(ApplicationCache, ProfilingLogger.Logger, dbContext.SqlSyntax, UmbracoConfig.For.UmbracoSettings()), 
      new PetaPocoUnitOfWorkProvider(dbFactory), 
      new FileUnitOfWorkProvider(), 
      new PublishingStrategy(evtMsgs, ProfilingLogger.Logger), 
      ApplicationCache, 
      ProfilingLogger.Logger, 
      evtMsgs); 
    } 
} 

public class CustomUmbracoApplication : Umbraco.Web.UmbracoApplication 
{ 
    ... 
    protected override IBootManager GetBootManager() 
    { 
     return new CustomBootManager(this); 
    } 
    ... 
} 
1

我做了一些工作,一把umbraco ,從控制檯應用程序運行它,然後使用Umbraco API調用Umbraco。 我相信我基於這個項目:https://github.com/sitereactor/umbraco-console-example

可能會有用。

+0

任何特別的事情你認爲可能與問題有關?我無法在這裏找到任何與我的問題相關的東西......雖然我確實注意到他們確實使用了保存命令。 – Jimmyt1988

+1

整個項目是一個很好的解決方案來運行不帶HttpContext的Umbraco API--所以如果你看看擴展了「普通」UmbracoApplicationBase的ConsoleApplicationBase這樣的類,你將會看到很多東西,工作 - 所以我會建議它不像嘲弄HttpContext那麼簡單。我確實使用上述項目作爲基礎,nad有一個控制檯應用程序,它能夠使用Umbraco API來處理當前內容(我們用它來實現自動Umbraco升級工具)。 – user369142

+0

啊,謝謝。我明白了,所以你從UmbracoApplicationBase繼承的事實意味着你可以返回你自己的BootManager,這又可以讓你覆蓋CreateServiceContext。 – Jimmyt1988

相關問題