HttpResponse对象空错误

时间:2011-11-15 03:15:51

标签: asp.net asp.net-mvc vb.net

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

任何想法为什么只有在从包含控制器内部显式调用时才能使用???

2 个答案:

答案 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()时,不会发生这种情况。