5

私の MVC コントローラーには、ブロブ ストリームを FileResult に渡すことによって Azure ブロブを返すいくつかのアクションがあります。このような:

    public FileResult DownloadReport(string Id)
    {
        // Look up model
        string fileName = messenger.ReportTitle(Id);

        // Get a reference to the blob
        CloudBlockBlob mainReportBlob = cloudBlobContainer.GetBlockBlobReference(Id);

        // Return as a FileResult
        using (var reportReader = mainReportBlob.OpenRead())
        {
            return File(reportReader , "application/pdf", fileName );
        }
    }

最近、Azure ストレージ ライブラリを最新のものに更新したところ、次の例外が発生し始めました。

System.NullReferenceException はユーザー コードによって処理されませんでした
。HResult=-2147467261
Message=オブジェクト参照がオブジェクトのインスタンスに設定されていません。
Source=Microsoft.WindowsAzure.Storage
StackTrace:
e:\projects\azure-sdk-for-net\microsoft-azure の Microsoft.WindowsAzure.Storage.Blob.BlobReadStreamBase.ConsumeBuffer(Byte[] buffer, Int32 offset, Int32 count) で-api\Services\Storage\Lib\Common\Blob\BlobReadStreamBase.cs:
e:\projects\azure の Microsoft.WindowsAzure.Storage.Blob.BlobReadStream.Read(Byte[] buffer, Int32 offset, Int32 count) の222 行目-sdk-for-net\microsoft-azure-api\Services\Storage\Lib\DotNetCommon\Blob\BlobReadStream.cs:
System.Web.Mvc.FileStreamResult.WriteFile(HttpResponseBase 応答)の 72 行目
System.Web.Mvc.FileResult.ExecuteResult (ControllerContext コンテキスト)
で System.Web.Mvc.ControllerActionInvoker.InvokeActionResult (ControllerContext controllerContext、ActionResult actionResult)
で System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive (IList 1 フィルター、Int32 filterIndex、ResultExecutingContext) preContext、ControllerContext controllerContext、ActionResult actionResult) 1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList

エラーは、Azure ライブラリ自体から発生しているようです。何か案は?

4

1 に答える 1

7

そのため、逆コンパイラを使用してステップスルーした後、BlobReadStreamBase.Dispose()メソッドが読み取られる前に呼び出されていることがわかりました。さらに掘り下げてみると、コントローラーからの戻りFile()は実際にはストリームを読み取らず、それを処理するために MVC の残りの部分に渡すだけのようです。

これが意味することは、using()MVC がパイプラインのさらに下にある Blob ストリームを読み取る前に、ブロックが Blob ストリームを閉じていたことです。アクションを次のように変更しました。

    public FileResult DownloadReport(string Id)
    {
        // Look up model
        string fileName = messenger.ReportTitle(Id);

        // Get a reference to the blob
        CloudBlockBlob mainReportBlob = cloudBlobContainer.GetBlockBlobReference(Id);

        // Return as a FileResult, DON'T place in a using() block or it will be closed early
        var reportReader = mainReportBlob.OpenRead();
        return File(reportReader , "application/pdf", fileName );
    }

これは機能します。さらに、逆コンパイラにブレークポイントを設定し、BlobReadStreamBase.Dispose() が後で呼び出されているため、MVC がパイプラインのさらに下にあるものをクリーンアップしていると考えられます。

なぜこれが以前に機能したのかはわかりません。Azure ライブラリで修正されたバグでしょうか?

于 2013-11-07T18:47:20.750 に答える