System.ArgumentNullException:值不能为null - 保存和发布时的Umbraco HTTPContext

时间:2016-11-22 13:35:45

标签: umbraco httpcontext

来源:https://gist.github.com/sniffdk/7600822

以下代码由http请求之外的活动运行,因此我需要模拟http上下文。

我像这样嘲笑了http上下文:

IO

我将此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

...发生以下错误。

  

System.ArgumentNullException:值不能为null。参数名称:   System.Web.HttpContextWrapper..ctor中的httpContext(HttpContext   httpContext)   Umbraco.Web.SingletonHttpContextAccessor.get_Value()at   Umbraco.Web.RequestLifespanMessagesFactory.Get()at   Umbraco.Core.Services.ContentService.SaveAndPublishDo(IContent   content,Int32 userId,Boolean raiseEvents)at   Umbraco.Core.Services.ContentService.Umbraco.Core.Services.IContentServiceOperations.SaveAndPublish(IContent   content,Int32 userId,Boolean raiseEvents)at   Umbraco.Core.Services.ContentService.SaveAndPublishWithStatus(IContent   content,Int32 userId,Boolean raiseEvents)

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

我认为相关问题来自:

RequestLifespanMessagesFactory.cs

反过来调用这个的实现:

SingletonHttpContextAccessor.cs

2 个答案:

答案 0 :(得分:1)

我与Umbraco合作,从控制台应用程序运行它,然后使用Umbraco API调用Umbraco。 我相信我是基于这个项目:https://github.com/sitereactor/umbraco-console-example

可能有用。

答案 1 :(得分:0)

感谢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);
    }
    ...
}