2016-11-22 9 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 идентификатор пользователя, булевы raiseEvents) при Umbraco.Core.Services.ContentService.Umbraco.Core.Services.IContentServiceOperations.SaveAndPublish (IContent содержание, Int32 USERID, булевы raiseEvents) в Umbraco.Core.Services .ContentService.SaveAndPublishWithStatus (содержимое IContent , Int32 userId, Boolean raiseEvents)

Как я обманываю контекст http без использования frowned upon HttpContext.Current = ...?


Я предполагаю, что соответствующий вопрос исходит от:

RequestLifespanMessagesFactory.cs

, который в свою очередь, называет реализацию этого:

SingletonHttpContextAccessor.cs

ответ

0

Thanks user369142. Это то, что закончилось тем, что работало:

Я также должен был убедиться, что я не поднимал никаких событий в вызовах SaveandPublish ... поскольку HttpContext ожидает, что там будут сообщения, зарегистрированные в контексте, но мы не издеваемся над ними. .. Если вы убедитесь, что события повышения являются ложными, он пропускает код, который это касается.

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 , запуская его из консольного приложения, а затем используя API Umbraco для вызова в Umbraco. Я считаю, что я основывал его на этом проекте: https://github.com/sitereactor/umbraco-console-example

Может быть полезно.

+0

Что-нибудь, в частности, вы думаете, может быть связано с проблемой? Я не могу найти ничего относительно моей проблемы здесь ... хотя я заметил, что они используют команду Save. – Jimmyt1988

+1

Весь этот проект является большим решением/решением для запуска API Umbraco без HttpContext - поэтому, если вы посмотрите на классы, подобные ConsoleApplicationBase, которые расширяют «нормальную» UmbracoApplicationBase, вы увидите немало вещей, которые необходимы для того, чтобы это работа - поэтому я бы предположил, что это не так просто, как просто издеваться над HttpContext. Я получил эту работу, используя вышеупомянутый проект в качестве базы, у которого было консольное приложение, которое смогло использовать API Umbraco для работы с текущим контентом (мы использовали его для автоматического инструмента обновления Umbraco). – user369142

+0

Ahhh, спасибо. Я вижу, поэтому сам факт, который вы наследуете от UmbracoApplicationBase, означает, что вы можете вернуть свой собственный BootManager, что, в свою очередь, позволяет переопределить CreateServiceContext. – Jimmyt1988