C# IDependencyResolver在一个请求中处理了两次

C# IDependencyResolver在一个请求中处理了两次,c#,dependency-injection,unity-container,asp.net-web-api2,owin,C#,Dependency Injection,Unity Container,Asp.net Web Api2,Owin,我有一个相当复杂的WebAPI2项目,使用Owin和依赖注入,使用Unity。我现在确实有一个控制器操作,它从请求.Content中获取MultipartContent,然后将其移交给一个服务(由DI创建),该服务将该文件临时存储到服务器的硬盘上。这是必需的,因为服务使用外部和本机DLL来读取此文件以进行某些验证和转换。因此,外部DLL将转换后的文件和转换结果(作为XML)另外存储在同一位置。我的服务现在读取转换结果并返回该结果。然后删除临时文件 现在的问题是,我自己的idependencyso

我有一个相当复杂的
WebAPI2
项目,使用
Owin
和依赖注入,使用
Unity
。我现在确实有一个控制器操作,它从
请求.Content
中获取
MultipartContent
,然后将其移交给一个服务(由DI创建),该服务将该文件临时存储到服务器的硬盘上。这是必需的,因为服务使用外部和本机DLL来读取此文件以进行某些验证和转换。因此,外部DLL将转换后的文件和转换结果(作为XML)另外存储在同一位置。我的服务现在读取转换结果并返回该结果。然后删除临时文件

现在的问题是,我自己的
idependencysolver
方法在该操作期间被调用了两次,这实际上破坏了内容,因此下一个请求也失败了。例如,我确实收到了无法创建控制器的错误,因为它在
System.Web.Http.HttpServer
上没有无参数构造函数或
ObjectDisposedException
。之后,DI容器被正确地重建,一切正常。等等所以每秒钟的请求都会失败

下面是一些代码:

Owin启动

[assembly: OwinStartup(typeof(MyNamespace.Startup))]
namespace myNamespace
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            HttpConfiguration httpConfiguration = new HttpConfiguration();
            httpConfiguration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
            app.UseCors(CorsOptions.AllowAll);

            IUnityContainer container = new UnityContainer();

            // setup dependency injection
            container.RegisterType<IFileConversionService, FileConversionService>();

            UnityConfig.RegisterControllers(container);

            // register routes
            WebApiConfig.Register(httpConfiguration);

            // setup dependency resolver
            httpConfiguration.DependencyResolver = new MyNamespace.UnityResolver(container);

            app.UseWebApi(httpConfiguration);
        }
    }
}
同样,这也没什么特别之处,因为它只是从网络上众多示例中的一个复制而来

现在控制器操作:

public async Task<IHttpActionResult> Upload()
{
    if (!Request.Content.IsMimeMultipartContent())
    {
        throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    }

    MultipartMemoryStreamProvider provider = new MultipartMemoryStreamProvider();
    await Request.Content.ReadAsMultipartAsync(provider);

    IList<MyFile> uploadFiles = new List<MyFile>();
    foreach (var file in provider.Contents)
    {
        MyFile myFile = new MyFile
        {
            FileName = file.Headers.ContentDisposition.FileName.Trim('\"'),
            Data = await file.ReadAsByteArrayAsync()
        };

        uploadFiles.Add(myFile);
    }

    List<ConversionResult> result = new List<ConversionResult>();
    foreach(MyFile file in uploadFiles)
    {
        result.AddRange(_fileConversionService.ImportFile(file));
    }

    if (result!= null && result.Count() == uploadFiles.Count)
    {
        return Ok(importedParts);
    }

    return BadRequest("One or more files could not be imported.");
}
现在问题来了。当我使用

_tempFilePath = AppDomain.CurrentDomain.BaseDirectory + TempDirectory;
一切正常


我想这与卷影复制有关…

Dispose()似乎不是线程安全的。还有为什么每次请求后都要拆下DI?通常我是为应用程序的生命周期构建DI的。@OndrejSvejdar拆掉DI并不是故意的。在
idependencysolver.BeginScope()
中创建了一个子容器,该子容器稍后将被释放,这似乎是正确的。在我上面的例子中,父容器也被处理掉了,这给我带来了所有的麻烦。问题是为什么要处理父容器,是谁造成的;当您点击Dispose()时,我可以请您分享调用堆栈上的内容吗?@OndrejSvejdar感谢您的努力!在这两种情况下,调用堆栈中的第一个元素都是
[External code]
,然后是
Dispose()
。所以这里没有什么启发。。。我很确定这是和创建/删除文件和文件夹有关的。这是否可能只发生在vs调试环境中?可能是因为vs中的浏览器链接。此工具本身会发出一些请求。请参见此处:()Dispose()内容似乎不是线程安全的。还有为什么每次请求后都要拆下DI?通常我是为应用程序的生命周期构建DI的。@OndrejSvejdar拆掉DI并不是故意的。在
idependencysolver.BeginScope()
中创建了一个子容器,该子容器稍后将被释放,这似乎是正确的。在我上面的例子中,父容器也被处理掉了,这给我带来了所有的麻烦。问题是为什么要处理父容器,是谁造成的;当您点击Dispose()时,我可以请您分享调用堆栈上的内容吗?@OndrejSvejdar感谢您的努力!在这两种情况下,调用堆栈中的第一个元素都是
[External code]
,然后是
Dispose()
。所以这里没有什么启发。。。我很确定这是和创建/删除文件和文件夹有关的。这是否可能只发生在vs调试环境中?可能是因为vs中的浏览器链接。此工具本身会发出一些请求。请看这里:()
public IEnumerable<ConversionResult> ImportFile(MyFile myFile)
{
    lock (_lock)
    {
        IEnumerable<ConversionResult> conversionResult = new List<ConversionResult>();
        try
        {
            string inputFile = SaveFileTemporarily(myFile);
            string inputFileExtension = Path.GetExtension(inputFile);
            string logFile = inputFile.Replace(inputFileExtension, ".txt");

            // check if the file can be validated/converted by the DLL
            if (ValidateFileExtension(inputFileExtension))
            {
                // call external DLL that writes log file and converted file
                ConvertFile(inputFile, logFile, inputFileExtension);

                conversionResult = ParseLogFile(logFile);
                if (!conversionResult.Any())
                {
                    // no errors found
                    conversionResult.Add(ConversionResult.NoError);
                }
            }
            else
            {
                conversionResult.Add(ConversionResult.UnknownFileType);
            }
        }
        finally
        {
            Directory.Delete(GenerateTempSavePath(myFile), true);
        }

        return conversionResult;
    }
}
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
_tempFilePath = Path.GetDirectoryName(path) + TempDirectory;
_tempFilePath = AppDomain.CurrentDomain.BaseDirectory + TempDirectory;