MVC 3. VB.NET我的应用程序中有以下控制器操作,通过下载将生成的PDF文件发送给用户。调用控制器本身时,该函数正常工作。但是当我从控制器外部调用该函数时,它会在遇到response.contenttype行时返回“对象引用未设置为对象的实例”错误。我已经验证所有的变量实际上都是在下面的动作...但是如果我尝试在另一个控制器中调用它,则没有骰子:
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
任何想法为什么只有在从包含控制器内部显式调用时才能使用???
答案 0 :(得分: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 :(得分:1)
你做不到。
ASP.Net MVC在创建控制器并调用操作时会为您做很多初始化 它创建一个ControllerContext,设置它的HttpContext,解析路由值,并做其他事情。
当你写new PrintController()
时,不会发生这种情况。