System.ArgumentNullException: 值不能为 null - Umbraco HTTPContext 保存和发布
System.ArgumentNullException: Value cannot be null - Umbraco HTTPContext on save and publish
来源:https://gist.github.com/sniffdk/7600822
以下代码是 运行 由 activity 在 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: Value cannot be null. Parameter name:
httpContext at System.Web.HttpContextWrapper..ctor(HttpContext
httpContext) at
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
这反过来又调用了这个的实现:
我用 Umbraco 做了一些工作,运行 它来自控制台应用程序,然后使用 Umbraco API 调用 Umbraco。
我相信我基于这个项目:https://github.com/sitereactor/umbraco-console-example
可能会有用。
感谢 user369142。这就是最终的工作:
我还必须确保我没有在 SaveandPublish 调用中引发任何事件...因为 HttpContext 期望在上下文中注册消息但我们不会模拟任何...如果您确定raise events 是 false,它会跳过关心那个的代码。
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);
}
...
}
来源:https://gist.github.com/sniffdk/7600822
以下代码是 运行 由 activity 在 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: Value cannot be null. Parameter name: httpContext at System.Web.HttpContextWrapper..ctor(HttpContext httpContext) at 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
这反过来又调用了这个的实现:
我用 Umbraco 做了一些工作,运行 它来自控制台应用程序,然后使用 Umbraco API 调用 Umbraco。 我相信我基于这个项目:https://github.com/sitereactor/umbraco-console-example
可能会有用。
感谢 user369142。这就是最终的工作:
我还必须确保我没有在 SaveandPublish 调用中引发任何事件...因为 HttpContext 期望在上下文中注册消息但我们不会模拟任何...如果您确定raise events 是 false,它会跳过关心那个的代码。
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);
}
...
}