我有一个控制器动作方法:
#include <Windows.h>
#include <Wininet.h>
#include <memory>
#pragma comment(lib, "Wininet.lib")
#include <iostream>
bool GetUrlCacheEntryInfo(const wchar_t* pUrl, std::unique_ptr<unsigned char[]>& pUrlCacheEntryInfo, DWORD nBufferSize = sizeof(INTERNET_CACHE_ENTRY_INFO))
{
std::unique_ptr<unsigned char[]> pTemporaryUrlCacheEntryInfo(new unsigned char[nBufferSize]);
if (GetUrlCacheEntryInfo(pUrl, reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(pTemporaryUrlCacheEntryInfo.get()), &nBufferSize) == FALSE)
{
const DWORD nError = GetLastError();
if (nError == ERROR_INSUFFICIENT_BUFFER)
{
pTemporaryUrlCacheEntryInfo.reset(new unsigned char[nBufferSize]);
if (GetUrlCacheEntryInfo(pUrl, reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(pTemporaryUrlCacheEntryInfo.get()), &nBufferSize) == FALSE)
{
return false;
}
}
else
{
return false;
}
}
pUrlCacheEntryInfo = std::move(pTemporaryUrlCacheEntryInfo);
return true;
}
void PrintUrlCacheEntryInfo(LPINTERNET_CACHE_ENTRY_INFO pUrlCacheEntryInfo)
{
std::cout << "Cache Entry Info:\n\tSize: " << pUrlCacheEntryInfo->dwStructSize << "\n\tUrl: ";
std::wcout << pUrlCacheEntryInfo->lpszSourceUrlName;
std::cout << "\n\tLocal File:";
std::wcout << pUrlCacheEntryInfo->lpszLocalFileName;
std::cout << "\n\tType: ";
switch (pUrlCacheEntryInfo->CacheEntryType)
{
case EDITED_CACHE_ENTRY:
std::cout << "EDITED_CACHE_ENTRY";
break;
case SPARSE_CACHE_ENTRY:
std::cout << "SPARSE_CACHE_ENTRY";
break;
case STICKY_CACHE_ENTRY:
std::cout << "STICKY_CACHE_ENTRY";
break;
case TRACK_OFFLINE_CACHE_ENTRY:
std::cout << "TRACK_OFFLINE_CACHE_ENTRY";
break;
case TRACK_ONLINE_CACHE_ENTRY:
std::cout << "TRACK_ONLINE_CACHE_ENTRY";
break;
default:
std::cout << "UNKNOWN";
break;
}
std::cout << "\n\tHeaders: ";
std::wcout << pUrlCacheEntryInfo->lpHeaderInfo;
std::cout << "\n";
}
int main(int argc, char** argv)
{
const wchar_t* pUrl = L"https://h6.msn.com/library/8.8/dapmsn.js";
std::unique_ptr<unsigned char[]> pUrlCacheEntryInfo;
if (GetUrlCacheEntryInfo(pUrl, pUrlCacheEntryInfo))
{
PrintUrlCacheEntryInfo(reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(pUrlCacheEntryInfo.get()));
}
else
{
std::wcout << L"Cache entry for url " << pUrl << L" was not found!\n";
}
return EXIT_SUCCESS;
}
我使用构造函数上课 RegisterTenantCommand :
public void Register([FromBody]RegisterTenantCommand message)
{
...
}
但是当我启动我的应用并执行此操作时,我有 httpContextAccessor = null 。
我该如何解决这个问题?
答案 0 :(得分:4)
似乎您将命令与来自UI框架的命令混淆(如ICommand
接口的WPF + MVVM实现)。
当前的实现也违反了SRP原则,其中一个类应该只负责一件事。您基本上处理输入(将其绑定到用户值)并执行它以及处理其中的执行逻辑。
命令/处理程序或CQRS模式中的命令仅仅是消息,它们只包含数据(可以或不可以序列化并通过消息总线发送以供其他后台进程处理)。
// ICommand is a marker interface, not to be confused with ICommand from WPF
public class RegisterTenantCommand : ICommand
{
public string TenantId { get; set; }
public string Name { get; set; }
}
命令处理程序包含一个标记接口及其实现(1:1关系,1个命令的1个处理程序)。
public interface ICommandHandler<T> where T : ICommand
{
void Handle(T command);
}
public class RegisterTenantCommandHandler : ICommandHandler<RegisterTenantCommand>
{
private readonly IHttpContext context;
// You should really abstract this into a service/facade which hides
// away the dependency on HttpContext
public RegisterTenantCommandHandler(IHttpContextAccessor contextAccessor)
{
this.context = contextAccesspor.HttpContext;
}
public void Handle(RegisterTenantCommand command)
{
// Handle your command here
}
}
在使用第三方IoC(如Autofac)时自动注册或使用内置IoC手动注册(此处我将使用内置):
services.AddTransient<ICommandHandler<RegisterTenantCommand>, RegisterTenantCommandHandler>();
您可以在动作或控制器或任何其他服务中注入它:
public class TenantController
{
public TenantController(ICommandHandler<RegisterTenantCommand> registerTenantHandler)
{
...
}
}
或行动
public Task<IActionResult> RegisterTenant(
[FromBody]RegisterTenantCommand command,
[FromService]ICommandHandler<RegisterTenantCommand> registerTenantHandler
)
{
registerTenantHandler.Handle(command);
}
当然,您可以进一步抽象这一点,只注入一个将解析和处理所有命令的单个接口类,然后调用它generalCommandHandler.Handle(command)
,它的实现将解析并处理它。
答案 1 :(得分:0)
默认情况下不再注册IHttpContextAccessor服务
IHttpContextAccessor可用于访问HttpContext 当前线程。但是,保持这种状态并非易事 性能成本因此已从默认设置中删除 服务。
依赖它的开发人员可以根据需要添加它:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
请参阅aspnet/Hosting#793进行讨论。