Printing from an ASP.NET page

Discussion in 'ASP .Net' started by Brett, Jul 10, 2008.

  1. Brett

    Brett Guest

    I have an ASP.NET page that displays work orders in a GridView. In that
    GridView is a checkbox column. When the user clicks a "Print" button, I
    create a report, using the .NET Framework printing classes, for each of the
    checked rows in the GridView. This works fine in the Visual Studio 2005
    development environment on localhost. But, when I move the page to the web
    server, I get the error "Settings to access printer
    '\\ServerName\PrinterName' are not valid." (See below.) I get the same
    error if I try this while logged into the server, but I can successfully
    print a test page from the server.



    This printer is installed on the server and is the default printer. The
    server is running Windows Server 2003 R2 Service Pack 2, IIS 6 and ASP.NET
    2.0.50727.0. Is there any way that I can have this report print when the
    page is hosted on the web server? Thank you!

    Settings to access printer '\\COLUMBIA\IT Hallway FS-3820N KX' are not
    valid.
    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.Drawing.Printing.InvalidPrinterException: Settings
    to access printer '\\COLUMBIA\IT Hallway FS-3820N KX' are not valid.

    Source Error:

    Line 194:Line 195: PrintDoc.Print()Line 196:
    PrintDoc.Dispose()Line 197: End Sub



    Source File: C:\Inetpub\wwwroot\MaintenanceManager\WorkOrders.aspx.vb
    Line: 195

    Stack Trace:

    [InvalidPrinterException: Settings to access printer '\\COLUMBIA\IT Hallway
    FS-3820N KX' are not valid.]
    System.Drawing.Printing.PrinterSettings.GetHdevmodeInternal() +123451
    System.Drawing.Printing.PrinterSettings.GetHdevmode(PageSettings
    pageSettings) +48
    System.Drawing.Printing.PrintController.OnStartPrint(PrintDocument document,
    PrintEventArgs e) +81
    System.Windows.Forms.PrintControllerWithStatusDialog.OnStartPrint(PrintDocument
    document, PrintEventArgs e) +33
    System.Drawing.Printing.PrintController.Print(PrintDocument document) +201
    System.Drawing.Printing.PrintDocument.Print() +111
    _Default.PrintWorkOrder() in
    C:\Inetpub\wwwroot\MaintenanceManager\WorkOrders.aspx.vb:195
    _Default.btnPrint_Click(Object sender, EventArgs e) in
    C:\Inetpub\wwwroot\MaintenanceManager\WorkOrders.aspx.vb:180
    System.Web.UI.WebControls.Button.OnClick(EventArgs e) +105
    System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
    +107
    System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String
    eventArgument) +7
    System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl,
    String eventArgument) +11
    System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33
    System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,
    Boolean includeStagesAfterAsyncPoint) +1746
     
    Brett, Jul 10, 2008
    #1
    1. Advertisements

  2. Are you creating a web or desktop application? I notice that the Stack Trace
    contains the following:

    System.Windows.Forms.PrintControllerWithStatusDialog.OnStartPrint(PrintDocument
    document, PrintEventArgs e) +33

    The System.Windows.Forms namespace is never used in an ASP.NET application.
    If you want to print an ASP.NET page, you will need to use the JavaScript
    window.print() method. If you want to have a printable version generated
    when the user clicks the button or link to print, I would suggest the
    following:

    1. Create another page that generates the appropriate report (probably using
    a querystring)
    2. In the link to this page, be sure to include target="_blank" so that the
    page opens in a new window
    3. Use the following for the body tag of the new page, which will print the
    page and then close it:

    <body onload="window.print();window.close();">

    This technique will allow the user to bring up their browser's print dialog,
    close the window, and return to the previous page with the click of a single
    button or link. If you are trying to make a desktop application, well, then,
    you are posting to the wrong newsgroup. Good Luck!
    --
    Nathan Sokalski

    http://www.nathansokalski.com/

     
    Nathan Sokalski, Jul 11, 2008
    #2
    1. Advertisements

  3. Hi Brett,

    As for the report printing, do you want it to print at the client-side
    machine or server-side machine. As Nathan has mentioned, ASP.NET web
    application is totally running separate from client-side browser
    environment. for printing, you have the following different choice:

    1. Let page opened in client-side webbrowser and user click browser's
    "print" menu to print. Or you can use javascript "window.print()" to print
    the current page. However, our server-side web application doesn't have
    much control on the client-side printing setting or printers

    2. You only want to print at server-side, then, you can use printing code
    in your asp.net server-side code , such code will only use printers at
    ASP.NET web server, and the client user will never see what happed for the
    printers at server-side.

    The reason why you'll see some different behavior(the client user can also
    see server-side printing code work) when using visual studo test server is
    as below:

    ** visual studio test server is a winform application which runs on local
    machine(under the current logon user).

    ** so if you use any desktop application code(such as winform code) in
    asp.net pages which hosted in visual studio test server, it will also be
    visible

    ** however, if you deploy the ASP.NET application to IIS, that's totally
    different. IIS worker process runs under a non-visible user session and
    under an different non-interactive user account.

    If you have anything unclear on this, please feel free to post here.

    Sincerely,

    Steven Cheng

    Microsoft MSDN Online Support Lead


    Delighting our customers is our #1 priority. We welcome your comments and
    suggestions about how we can improve the support we provide to you. Please
    feel free to let my manager know what you think of the level of service
    provided. You can send feedback directly to my manager at:
    .

    ==================================================
    Get notification to my posts through email? Please refer to
    http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    ications.

    ==================================================
    This posting is provided "AS IS" with no warranties, and confers no rights.

    --------------------
     
    Steven Cheng [MSFT], Jul 11, 2008
    #3
  4. Brett

    Brett Guest

    Thank you, Steven and Nathan, for your quick response!

    This is a web application and will print to a network printer. Ideally, it
    would print from the client-side, but server-side will be OK, because all
    users are likely to use the same printer.

    The application has been using the javascript "window.print" until now, but
    the users would like to be able to select multiple rows from the GridView
    and print them all with one click. Is this possible?

    Thanks!
    Brett
     
    Brett, Jul 11, 2008
    #4
  5. If you want it to print specific rows, do something like add a checkbox to
    each row and then generate a page using some variation of my original
    suggestion.
     
    Nathan Sokalski, Jul 11, 2008
    #5
  6. Hi Brett,

    Thanks for your reply.

    For the new question you mentioned. I would suggest you consider the
    following approach:

    1. One the original page (with Gridview), provide checkbox to let user
    choose the rows to print

    2. When the user click a print button, the page will postback, and you can
    find all the selected rows(by looping the gridview to check checkbox
    values) and redirect the user to a new page which will only display those
    selected rows.

    thus, on the new page the user can print what they exactly want. Just an
    idea of generate a print version. How do you think?

    Sincerely,

    Steven Cheng

    Microsoft MSDN Online Support Lead


    Delighting our customers is our #1 priority. We welcome your comments and
    suggestions about how we can improve the support we provide to you. Please
    feel free to let my manager know what you think of the level of service
    provided. You can send feedback directly to my manager at:
    .

    ==================================================
    Get notification to my posts through email? Please refer to
    http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    ications.

    ==================================================
    This posting is provided "AS IS" with no warranties, and confers no rights.
    --------------------
     
    Steven Cheng [MSFT], Jul 14, 2008
    #6
  7. Brett

    Brett Guest

    The problem with <body onload="window.print();window.close();"> is that the
    browser still prompts the user about closing the window, so it doesn't save
    the user any keystrokes. It is just as easy for them to close the window or
    go to the previous page themselves. When selecting multiple reports, the
    users will not like having to confirm closing the window for each report.
    An alternative to "window.close" might be "history.go(-1)" but that does not
    wait for the user to print before returning to the previous page.

    Your latest suggestion is close, but I need a separate page for each
    selected record, showing additional data (from the same table) that is not
    shown in the GridView.

    I have also tried using a ReportViewer control on the page, but I had
    problems with that, too, including a persistent "parameter is missing a
    value" error. Do you think the use of ReportViewer may have some potential?

    The original server-side printing, using .NET printing methods works so
    nicely in the Visual Studio test environment, it is disappointing that it
    cannot be used on the real web server.
     
    Brett, Jul 14, 2008
    #7
  8. Hi Brett,

    Thanks for your further reply.

    As for ReportViewer, I think the printing functionality is also quite
    limited since you cannot control the printing setting in code(but let the
    user choose when click print button).

    For server-side printing, it is not completely unavailable, but no
    recommended. You can try the following:

    1. first check your server-side printing code(which use some winform
    printing code) to ensure that the one will not require any interactive
    operations such as prompt dialog box that need a user to respond. All the
    code should be able to finish programmtically without UI.

    2. You can try changing your ASP.NET application's worker process
    account(for IIS6 it is the application pool identity). Switch it to an
    interactive user account such a domain user account or local logon user so
    that it can access the certain printers. Or you can consider using
    impersonate at runtime to let your application running under a certain user
    account.

    Here are some information about IIS worker process identity and impersonate
    in ASP.NET

    #How To: Use Impersonation and Delegation in ASP.NET 2.0
    http://msdn.microsoft.com/en-us/library/ms998351.aspx

    #How to implement impersonation in an ASP.NET application
    http://support.microsoft.com/kb/306158

    #IIS Worker processes & windowstation/desktops
    http://blogs.msdn.com/nicd/archive/2007/05/10/iis6-winstation-desktop-settin
    gs.aspx

    BTW, if the printing task is a frequently used functionality on your
    webserver, I suggest you also consider the following approach:

    * create a separate winform application running on the server which will
    receive printer request(with necessary data) and do the printing task to
    certain printers on the server

    * Your ASP.NET application will always send printing task request to that
    winform application. the communication channel maybe any existing remoting
    approach such as : remoting, webservice, WCF, MSMQ....

    How do you think?

    Sincerely,

    Steven Cheng

    Microsoft MSDN Online Support Lead


    Delighting our customers is our #1 priority. We welcome your comments and
    suggestions about how we can improve the support we provide to you. Please
    feel free to let my manager know what you think of the level of service
    provided. You can send feedback directly to my manager at:
    .

    ==================================================
    Get notification to my posts through email? Please refer to
    http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    ications.

    ==================================================
    This posting is provided "AS IS" with no warranties, and confers no rights.




    --------------------
    <e#>
     
    Steven Cheng [MSFT], Jul 15, 2008
    #8
  9. Brett

    Brett Guest

    Thank you for your continuing support on this.

    For the server-side printing approach, I tried changing the worker process
    account to an interactive user account, but I still got the same message
    that "Settings to access printer '\\servername\printername' are not valid."
    To do this, I:
    - created a new application pool
    - added a local account on the web server
    - added the new account to the IIS_WPG group
    - made the new account the worker account for the new application pool
    - made the new application pool the app pool for my application
    - logged onto the web server with the new account and successfully tested
    printing from that account

    Since this is a network printer, I then tried changing the worker process
    account to a network account, but I continued to get the same error message.
    Do you have any other ideas what may cause this error?

    For the ReportViewer approach, I got it to create the report, which the user
    can export to PDF and then print. That's a couple extra steps for the user,
    and the overall functionality of ReportViewer is restrictive, when compared
    to writing your own printing code.
     
    Brett, Jul 15, 2008
    #9
  10. Thanks for your reply Brett,

    Here I found a forum thread which mentioned a similar question. For
    accessing network printer, you can refer to some points mentioned there:

    * if you use a network/domain account, verify whether that account has
    correct permission to access the network printer(test the same code, same
    account in a desktop app)

    * someone also mentioned approach to use some printer port redirection
    component or tool to map a local print port to a remote printer

    #Access Your Network Printer
    http://forums.asp.net/t/587341.aspx

    BTW, is it possible that the printing part be separated from the main
    ASP.NET application and run it as a desktop one and let ASP.NET send
    printing request to it so that the actual report printing is done in the
    desktop application.

    Sincerely,

    Steven Cheng

    Microsoft MSDN Online Support Lead


    Delighting our customers is our #1 priority. We welcome your comments and
    suggestions about how we can improve the support we provide to you. Please
    feel free to let my manager know what you think of the level of service
    provided. You can send feedback directly to my manager at:
    .

    ==================================================
    Get notification to my posts through email? Please refer to
    http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    ications.
    ==================================================
    This posting is provided "AS IS" with no warranties, and confers no rights.

    --------------------
     
    Steven Cheng [MSFT], Jul 16, 2008
    #10
  11. Brett

    Brett Guest

    Yes, I could run the printing part as a Winform application. I'm not sure
    how I should implement it. (.NET remoting? Web service?) The
    communication between applications would be a new area for me.

    I found an article on MSDN that shows how to use a console application to
    print a local report without previewing it:
    http://msdn.microsoft.com/en-us/library/ms252091(VS.80).aspx
    When I ran the console application , it successfully printed the report, but
    when I tried to call the console app from the web app, I got
    "PrintLocalReport has encountered a problem and needs to close."

    Error signature:
    EventType : clr20r3 P1 : printlocalreport.exe P2 : 1.0.0.0
    P3 : 487e4d71 P4 : mscorlib P5 : 2.0.0.0 P6 : 471ebc5b
    P7 : 3404
    P8 : d8 P9 : system.io.filenotfoundexception

    The following code fails at "Dim p As System.Diagnostics.Process."

    Dim filePath As String = Server.MapPath("PrintLocalReport.exe")

    Dim info As System.Diagnostics.ProcessStartInfo = New
    System.Diagnostics.ProcessStartInfo(filePath, "")

    info.UseShellExecute = False

    Dim p As System.Diagnostics.Process =
    System.Diagnostics.Process.Start(info)

    p.Start()


    I don't know what file was not found. I did a "File.exists(filepath)" and
    it returned "True"
     
    Brett, Jul 16, 2008
    #11
  12. Thanks for your reply Brett,

    Yes, webservice or even simple network socket programming is ok(or if you
    can use .net 3.0, WCF will be much more convenient). Also, if you are
    familar with MSMQ programming, you can consider make each print request as
    a MSMQ message and send to a message queue, and your target winform
    application constantly pick messages from queue and perform printing.

    For the console application, do not call it from your ASP.NET application,
    that way, you are doing the samething as you try calling winform printing
    code in asp.net application since that will make the consile running in the
    same user context of the ASP.NET web applicaction. You should run the
    console or winform application from a logon user context and let the
    asp.net application communicate it via some remote communication methods.

    Sincerely,

    Steven Cheng

    Microsoft MSDN Online Support Lead


    Delighting our customers is our #1 priority. We welcome your comments and
    suggestions about how we can improve the support we provide to you. Please
    feel free to let my manager know what you think of the level of service
    provided. You can send feedback directly to my manager at:
    .

    ==================================================
    Get notification to my posts through email? Please refer to
    http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    ications.
    ==================================================
    This posting is provided "AS IS" with no warranties, and confers no rights.

    --------------------
    <e#>
    <OC0d#>
    <>
    <#>
    <>
     
    Steven Cheng [MSFT], Jul 17, 2008
    #12
  13. Brett

    Brett Guest

    I don't know anything about inter-process communication, and I can't really
    afford to spend more time at this point, experimenting with every possible
    method to see which, if any, will actually work for me. I cannot believe
    that simply printing a report from a web application could be so difficult.

    In all my research, I found an article that said that the print button was
    available for local reports on the Visual Studio 2008 ReportViewer. So, I
    upgraded my project to VS08. Lo and behold, there was the print button.
    Works like a charm...in the development environment. So, I copied the web
    form and the code-behind file to the server. I also installed the
    redistributable for the Report Viewer on the web server. I ran the
    application on the server, and I got the parser error shown below. I then
    added this line to the web.config:
    <add verb="*" path="Reserved.ReportViewerWebControl.axd" type =
    "Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms,
    Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

    Then, I got the compilation error below:

    Compilation Error
    Description: An error occurred during the compilation of a resource required
    to service this request. Please review the following specific error details
    and modify your source code appropriately.
    Compiler Error Message: BC30560: 'ReportDataSource' is ambiguous in the
    namespace 'Microsoft.Reporting.WebForms'.
    Source Error:
    Line 241:
    Line 242: 'Associate thisDataSet (now loaded with the stored
    procedure result) with the ReportViewer datasource
    Line 243: Dim datasource As New
    ReportDataSource("DataSet1_SelectWorkOrder", thisDataSet.Tables(0))

    This looks like an error in my code, but it had worked in the development
    environment.




    Parser Error
    Description: An error occurred during the parsing of a resource required to
    service this request. Please review the following specific parse error
    details and modify your source file appropriately.

    Parser Error Message: Could not load file or assembly
    'Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral,
    PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system
    cannot find the file specified.

    Source Error:

    Line 2: EnableEventValidation = "false" Inherits="_Default"
    Title="Maintenance Manager: Work Orders" Trace="false" %>
    Line 3:
    Line 4: <%@ Register Assembly="Microsoft.ReportViewer.WebForms,
    Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    Line 5: Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
    Line 6:

    Source File: /MaintenanceManager/WorkOrdersvs08.aspx Line: 4

    Assembly Load Trace: The following information can be helpful to determine
    why the assembly 'Microsoft.ReportViewer.WebForms, Version=9.0.0.0,
    Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' could not be loaded.

    WRN: Assembly binding logging is turned OFF.
    To enable assembly bind failure logging, set the registry value
    [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
    Note: There is some performance penalty associated with assembly bind
    failure logging.
    To turn this feature off, remove the registry value
    [HKLM\Software\Microsoft\Fusion!EnableLog].



    --------------------------------------------------------------------------------
    Version Information: Microsoft .NET Framework Version:2.0.50727.1433;
    ASP.NET Version:2.0.50727.1433
     
    Brett, Jul 17, 2008
    #13
  14. Thanks for your reply Brett,

    Per the error message you provided, it indicate that the runtime cannot
    locate the reportviewer control's assembly.As for ReportViewer controls(the
    winform and webform ones), they're part of the components shipped with
    Visual Studio instead of .net framework:

    #ReportViewer Controls (Visual Studio)
    http://msdn.microsoft.com/en-us/library/ms251671.aspx

    therefore, they're not included in .net framework built-in components. For
    a production server which only have .net framework installed(but no visual
    studio), it hasn't ReportViewer controls. For such case, you need to deploy
    the reportviewer control to the server first.

    #Deploying Reports and ReportViewer Controls
    http://msdn.microsoft.com/en-us/library/ms251723.aspx

    The redistributable package of reportviewer is included in visual studio,
    you can also download it and install it on the server.
    #Microsoft Report Viewer Redistributable 2008
    http://www.microsoft.com/downloads/details.aspx?FamilyID=cc96c246-61e5-4d9e-
    bb5f-416d75a1b9ef&DisplayLang=en

    Sincerely,

    Steven Cheng
    Microsoft MSDN Online Support Lead


    Delighting our customers is our #1 priority. We welcome your comments and
    suggestions about how we can improve the support we provide to you. Please
    feel free to let my manager know what you think of the level of service
    provided. You can send feedback directly to my manager at:
    .

    ==================================================
    Get notification to my posts through email? Please refer to
    http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    ications.
    ==================================================
    This posting is provided "AS IS" with no warranties, and confers no rights.





    --------------------
     
    Steven Cheng [MSFT], Jul 18, 2008
    #14
  15. Brett

    Brett Guest

    After trying several different approaches, it turns out that upgrading the
    project to Visual Studio 2008 and using the newer ReportViewer was the
    solution for me. Thanks for your efforts.

    Brett
     
    Brett, Jul 18, 2008
    #15
  16. Hello there, I think we are making this much more difficult than it is.

    As I understand, you have a page which has a gridview of records
    containing some, but not all, record information that already contains a
    list of checkboxes next to each record and a print button.

    What you would need to do is:
    1) Click the Print button with some records selected.

    2) Have JS handler to determine checked values and send
    the keys in a querystring to another report page.

    3) On the page generated by report page wrap records with
    a div using CSS style PageBreak-after:always;

    Viola, the page will have all records and the records will print on
    individual pages.
     
    jt007superman jt007superman, Jul 20, 2008
    #16
  17. Thanks for your reply Brett,

    I'm glad that you've got it working. If there is anything else we can help
    in the future, please feel free to post here.

    Sincerely,

    Steven Cheng

    Microsoft MSDN Online Support Lead


    Delighting our customers is our #1 priority. We welcome your comments and
    suggestions about how we can improve the support we provide to you. Please
    feel free to let my manager know what you think of the level of service
    provided. You can send feedback directly to my manager at:
    .

    ==================================================
    Get notification to my posts through email? Please refer to
    http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    ications.

    ==================================================
    This posting is provided "AS IS" with no warranties, and confers no rights.

    --------------------
     
    Steven Cheng [MSFT], Jul 21, 2008
    #17
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.