2011-11-15 64 views
1

MVC 3. VB.NET我在我的應用程序中通過下載將生成的PDF文件發送給用戶時有以下控制器操作。當控制器本身被調用時,該函數可以正常工作。但是,當我從控制器外部調用函數時,只要它碰到response.contenttype行,就會返回「對象引用未設置爲對象的實例」錯誤。我已經驗證了所有的變量都在事實上,它使以下面的動作......但沒有骰子,如果我嘗試在其他控制器稱之爲:HttpResponse對象空錯誤

Dim _print as new PrintController 
    _print.showUserPDF(firstName,lastName) 
    return RedirectToAction("Registrants") 

在PrintController功能是引發錯誤是:

Function showUserPDF(ByVal pdfName As String, ByVal fileName As String, ByVal _directory As String) As ActionResult 
     If Not String.IsNullOrEmpty(pdfName) Then 
      Response.ContentType = "application/pdf" 
      Response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName) 
      Response.TransmitFile(pdfName) 
      Response.[End]() 

      Dim FileToDelete As String 

      FileToDelete = pdfName 

      If System.IO.File.Exists(FileToDelete) = True Then 
       System.IO.File.Delete(FileToDelete) 
      End If 

      Directory.Delete(_directory) 
      Return Nothing 
     End If 
     Return Nothing 

    End Function 

任何想法,爲什麼這隻有在明確從它的包含控制器內部調用時才起作用?

回答

3

顯然,當從另一個控制器調用時,該方法沒有設置Response對象,也不應該存在(a)它不是由MVC框架創建的,或者(b)您沒有通過顯式的方式填充HttpContext屬性ControllerContext。這實際上是在兩個控制器之間下載內容和共享代碼的錯誤方式。

首先,您應該使用FileResult,使用採用字節數組的簽名,因爲您可能會刪除該文件,從控制器下載文件。 FileResult明確地被設計爲執行此操作。您不應直接寫入控制器的響應,因爲這違反了MVC基本關注點的分離。

其次,爲了共享代碼,您應該將代碼抽象到一個共享基礎控制器,從該控制器派生或者輔助類,最好是前者。這樣你就可以直接在框架創建的控制器中使用該方法,並且不需要實例化另一個控制器來調用該方法。

最後,你不能同時提供一個文件來下載和重定向到相同的響應。如果需要,你可能想通過javascript處理這個客戶端。請注意文件下載應該讓你在同一頁面上。

對於任何語法或其他錯誤,我很抱歉。我讀VB比我寫得好

Public Class ExtendedControllerBase 
    Inherits Controller 

    Function showUserPDF(ByVal pdfName As String, ByVal fileName As String, ByVal _directory As String) As ActionResult 
      If Not String.IsNullOrEmpty(pdfName) Then 

       Dim input As New FileStream(pdfName, FileMode.Open) 
       Dim bytes(CInt(input.Length - 1)) As Byte 
       input.Read(bytes, 0, CInt(input.Length)) 

       Dim FileToDelete As String 

       FileToDelete = pdfName 

       If System.IO.File.Exists(FileToDelete) = True Then 
        System.IO.File.Delete(FileToDelete) 
       End If 

       Directory.Delete(_directory) 
       Return File(bytes, "application/pdf", fileName) 
      End If 
      Return Content("") 'You might want to throw an exception here? 

     End Function 
End Class 

Public Class PrintController 
    Inherits ExtendedBaseController 

    ... 

End Class 
1

你不能那樣做。

當你創建一個控制器並調用一個動作時,ASP.Net MVC會爲你做很多初始化。
它創建一個ControllerContext,設置它的HttpContext,分析路由值,並執行其他操作。

當你寫new PrintController(),沒有發生。