2

ASP.NET MVC アクションで、ユーザー情報を含む CSV ファイルを返そうとしています:

  IList<UserModel> users = _repository.GetUsers();

  MemoryStream stream = new MemoryStream;
    using (StreamWriter writer = new StreamWriter(stream)) {
      using (CsvWriter csv = new CsvWriter(writer)) {
        csv.Configuration.With(x => {
          x.AutoMap<UserModel>();
          x.RegisterClassMap<UserModelCsvMapper>();
        });            
        csv.WriteRecords(reply.Users);
        writer.Flush();
        return File(stream, "text/csv", "Users.csv");
      }
    }

そして、私は次のマッパーを持っています:

public class UserModelCsvMapper : CsvClassMap<UserModel> {
  public override void CreateMap() {
    Map(x => x.Name).Name("Name");
    Map(x => x.Email).Name("Email");
    Map(x => x.Linked).Name("Linked");
  } // CreateMap
} // UserModelCsvMapper

私の CSV ライターは空に見え、ストリームを返すと次のエラーが表示されます。

((System.IO.Stream)(stream)).WriteTimeout' threw an exception of type 'System.InvalidOperationException'

そして、私はエラーページを取得します:

Cannot access a closed Stream.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ObjectDisposedException: Cannot access a closed Stream.

更新: スタック トレースの追加

閉じたストリームにアクセスできません。説明: 現在の Web 要求の実行中に未処理の例外が発生しました。エラーの詳細とコード内のどこでエラーが発生したかについては、スタック トレースを確認してください。

例外の詳細: System.ObjectDisposedException: 閉じられたストリームにアクセスできません。

ソース エラー:

現在の Web 要求の実行中に未処理の例外が生成されました。例外の発生元と場所に関する情報は、以下の例外スタック トレースを使用して特定できます。

スタックトレース:

[ObjectDisposedException: 閉じたストリームにアクセスできません。] System.IO._ Error.StreamIsClosed() +57 System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count) +10909062 System.Web.Mvc.FileStreamResult .WriteFile(HttpResponseBase 応答) +157 System.Web.Mvc.FileResult.ExecuteResult(ControllerContext コンテキスト) +296 System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext、ActionResult actionResult) +39 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive (IList 1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +116 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList1 フィルター、Int32 filterIndex、ResultExecutingContext preContext、ControllerContext controllerContext、ActionResult actionResult) +529 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +529 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList1 フィルター、ActionResult actionResult) +106 System.Web.Mvc.Async.<>c _DisplayClass2b.b_ 1c() +321 System.Web.Mvc.Async.<>c _DisplayClass21.b_ 1e(IAsyncResult asyncResult) +185 System. Web.Mvc.Async.WrappedAsyncResult 1.CallEndDelegate(IAsyncResult asyncResult) +42 System.Web.Mvc.Async.WrappedAsyncResultBase1.End() +133 System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult、Object タグ) +56 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) + 40 System.Web.Mvc.Controller.b _1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +34 System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +70 System.Web.Mvc.Async.WrappedAsyncResultBase1.End() +139 System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult、Object タグ) +59 System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult、Object タグ) +40 System.Web .Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +44 System.Web.Mvc.Controller.b_ 15(IAsyncResult asyncResult、コントローラーコントローラー) +39 System.Web.Mvc.Async.WrappedAsyncVoid 1.CallEndDelegate(IAsyncResult asyncResult) +62 System.Web.Mvc.Async.WrappedAsyncResultBase1.End() +139 System.Web .Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult、Object タグ) +59 System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult、Object タグ) +40 System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +39 System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +39 System.Web.Mvc.MvcHandler.b_5(IAsyncResult asyncResult、ProcessRequestState innerState) +39 System.Web.Mvc.Async.WrappedAsyncVoid 1.CallEndDelegate(IAsyncResult asyncResult) +70 System.Web.Mvc.Async.WrappedAsyncResultBase1.End() +139 System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult、Object タグ) +59 System.Web. Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult、Object タグ) +40 System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +40 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult 結果) +38 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9514928 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

ありがとう、ミゲル

4

1 に答える 1

4

using ステートメントは、FileResult で返すメモリ ストリームを閉じています。

これで修正されるはずです。MemoryStreamブロックの外側を宣言します。ストリームがストリームに完全に書き込まれると、フレームワークによって閉じられResponseます (ただし、現在のところ閉じることは必須ではありませんMemoryStream。ガベージ コレクトされると、適切にクリーンアップされます。

IList<UserModel> users = _repository.GetUsers();

var stream = new MemoryStream();
using (StreamWriter writer = new StreamWriter(stream)) {
  using (CsvWriter csv = new CsvWriter(writer)) {
      csv.Configuration.With(x => {
      x.AutoMap<UserModel>();
      x.RegisterClassMap<UserModelCsvMapper>();  
    });            
    csv.WriteRecords(reply.Users)
    writer.Flush();
    return File(stream, "text/csv", "Users.csv");
  }
}

または、FileResponse の Byte[] オーバーロードを使用できます。

using (var stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
using (CsvWriter csv = new CsvWriter(writer) {
  csv.Configuration.With(x => {
    x.AutoMap<UserModel>();
    x.RegisterClassMap<UserModelCsvMapper>();  
  })        

  //use the users that you just retrieved from the repository
  csv.WriteRecords(users)
  writer.Flush();

  return File(stream.ToArray(), "text/csv", "Users.csv");
}
于 2014-03-07T14:12:41.017 に答える