Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement printing in ASP.Net MVC3

As part of my current task in a given list of items, user can select some of them and invoke 'Print' no the selected items.

For each selected item we need to print the details. It is similar to printing invoices of selected items in a sales system.

I have created a partial view to write each record details but I am not sure how to use it as per my requirement.

Can I call jQuery print on document.ready to achieve my requirement?

As @Levib suggested, calling partial view in my PrintView. And PrintView's document.reay function is calling window.print. But when I try to invoke 'Print', I can not see print dialogue.

This is my view,

@section Styles
{
    <link rel="stylesheet" href="AdminStyle.css" type="text/css" media="all" />
    <link rel="stylesheet" href="AdminPrintOrder.css" type="text/css" media="print" />
}

@foreach (var item in Model)
{
    <div id="content" style="page-break-before: always">
        @{Html.RenderPartial("_OrderDetailView", item);}
    </div>   
}

@section scripts
{
    <script type="text/javascript">
        $(document).ready(function () {
            debugger;
            window.print();
        });
    </script>
}

And my print invoker view is

 function printInvoices(){
            $.ajax({
                type: 'POST',
                url: '/Batch/PrintInvoices',
                data: '{ "allocationId" : "' + unSelected.toString() + '"}',
                contentType: "application/json; charset=utf-8",
                traditional: true,
                success: printedView,
                error: errorInSubscribing
            });
        }

Do I need to handle ajax reposne to populate print dialogue.

 function printedView() {
            unSelected = [];
        }

And controller action is

[HttpPost]
        public ActionResult PrintInvoices(string allocationId)
        {
            var context = new BatchContext();
            var orderDetails =  context.GetOrderDetails(RetriveList(allocationId));
            return View(orderDetails);
        }
like image 232
Naresh Avatar asked Nov 29 '12 15:11

Naresh


2 Answers

  • Define a print stylesheet for your page. You do this by using the @media print declaration.
  • What you can then do is wrap each partial view on the page that you are going to print in a div and apply the 'page-break-before: always' CSS attribute to it.

This will ensure that each partial view ends up on a different page. Call 'window.print()' on the page load and you're done!


Given the extensive questions posed in the comments for this answer, here is a more detailed description of what needs to be done:

Preparation

  • A stylesheet needs to be defined and applied to the page which defines what the page will look like when printed.
    • This can either be done by using a @media print { } declaration in an existing stylesheet, or by applying the media="print" attribute to the link tag in your page which includes the stylesheet. You appear to have done this correctly.
    • This stylesheet must include a page-break-before: always declaration for all elements before which you would like there to be a page break. You seem to have done this with inline styles. Personally I would have rather done this in the print stylesheet than as an inline style. This step is integral to you being able to print one item per page.

Printing

  • window.print() allows you as the page author to define when the page is printed. This does the same thing as CTRL + P or as clicking the print button, except you can do it from your JavaScript.
  • Ajax has nothing intrinsically to do with printing. Ajax is a means to asynchronously make HTTP calls from your page without changing or reloading it and updating your page as a result. If you wanted to dynamically populate your page with items to print based on user input, then you could very well do so with Ajax. If you merely want to print the page, then you don't need to use Ajax. the navigator.**

Two important points:

  • window.print() prints the page that is currently onscreen. If you want to print a different page, you need to load the other page in some way shape or form (perhaps through a popup) and call window.print() on that page.
  • The print stylesheet defines what the printed page will look like in contrast to the onscreen version. This means that you can have a page of items and lots of other stuff, and print only the items when the user clicks the print button. You would do this by setting the display: none property in your print stylesheet on all the elements that you do not want to appear on the printed page.

About PDFs:

I have nothing against exporting pages to PDF when necessary, but as you did not specifically ask about a PDF solution, I have given you the HTML+CSS solution to your question. PDFs also take a minute to generate and load. They are great, however, when your users will want to save copies of what they are printing. If this is the case for your site I strongly recommend that you consider such a solution.

Testing:

How do you test a print stylesheet? The easiest way is to simply click the print button in Chrome which will show you a lovely preview of what your site is going to look like when it is printed.

Final word:

For now, forget about window.print() and just focus on getting your page looking like it should by applying the appropriate CSS. Write your CSS, run your page, look at the output in Chrome, modify your print stylesheet as needed... Rinse and repeat. Only once you have the page appear exactly as you want it when clicking the print button should you then look at calling the print function automatically in your JavaScript.

like image 192
Levi Botelho Avatar answered Nov 19 '22 06:11

Levi Botelho


How I do printing in MVC:

  1. Create a view with exactly what you want to print layed out how you want it to look
  2. Use the Rotativa library to turn your MVC View in a pdf document.

Simple as changing your Action to look like this

public ActionResult PrintInvoice(int invoiceId)
{
  return new ActionAsPdf(
                 "Invoice", 
                 new { invoiceId= invoiceId }) 
                 { FileName = "Invoice.pdf" };
}

I believe it will obey the css page-break, so if you need to only print one item per page you can use that markup to force items to new pages.

like image 7
Malcolm O'Hare Avatar answered Nov 19 '22 05:11

Malcolm O'Hare