.ASP.NET Batch PDF create using provided list of ID's

Hi all,

Need some help modifying an .aspx function to loop through a list and generate PDF files.  The list will be generated later, but assume it is a basic comma-delimited list of id's like "100278", "100279", 100280", etc.

The .aspx file, as it exists now.  I'm pasting the whole thing to show existing references.

I need to create a new function similar to the btnPDF_Click() function, but it needs to loop through a list of Manifest numbers to create individual PDF's to a local directory (instead of using the single Manifest declared in the Page_Load() function).  

Business case: a user needs to re-download and re-print 900 of these things - doing it one-by-one would be painful.  

Any help would be much appreciated!

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using ExtenData.MobilityCommon.Common.Util;
using Able.Data;
using Able.Web;
using System.IO;

public partial class Manifests_View : System.Web.UI.Page
{
    private Manifest manifest = null;
    private ManifestDetailCollection detailList = new ManifestDetailCollection();
    private string redirect = "Default";

    protected void Page_Load(object sender, EventArgs e)
    {
        manifest = Manifest.FetchByID(ServiceHelper.getInt(Request["ManifestId"]));
        if (manifest == null)
        {
            Response.Redirect("Default.aspx");
            return;
        }
        else
        {
            Top1.Title = "View Manifest";
            Able.Web.HistoryManager.AddPage(Request.Url.PathAndQuery, "View Manifest: " + manifest.ManifestNumber);
        }

        if (new ConfigManager().GetBool("Allow Fax"))
            pnlFax.Visible = true;

        if (ServiceHelper.ifNull(Request["redirect"]).Length > 0)
            redirect = Request["redirect"];

        lblPageTitle.Text = Top1.Title;

        if (Roles.IsUserInRole("XTend Administrator") || Roles.IsUserInRole("Administrator"))
            btnAudit.Visible = true;

        if (manifest.ManifestStatus == ManifestStatus.Disposed)
            btnEdit.Visible = false;
    }

    protected void btnPdf_Click(object sender, EventArgs e)
    {
        Response.Clear();
        Response.Charset = "";

        Response.ContentType = "application/pdf";
        Response.AddHeader("Content-Disposition", "attachment; filename=\"" + manifest.ManifestNumber + ".pdf\"");

        Dictionary<string, object> parms = new Dictionary<string, object>();
        parms.Add("Include Header", true);
        byte[] bytes = ManifestPdf.Generate(manifest, File.ReadAllText(Server.MapPath("~/Manifests/" + ManifestPdf.GetXmlFileName(manifest))), parms);

        Response.OutputStream.Write(bytes, 0, bytes.Length);

        Response.Flush();
        Response.End();
    }

    protected void btnSendPdf_Click(object sender, EventArgs e)
    {
        Dictionary<string, object> parms = new Dictionary<string, object>();
        parms.Add("Include Header", true);
        byte[] bytes = ManifestPdf.Generate(manifest, File.ReadAllText(Server.MapPath("~/Manifests/" + ManifestPdf.GetXmlFileName(manifest))), parms);

        string email = txtEmails.Text.Replace(';', ',');

        List<string> emails = new List<string>();
        string[] split = email.Split(',');
        foreach (string s in split)
            emails.Add(s.Trim());

        AbleUser user = AbleUser.FetchUserByUsername(Page.User.Identity.Name);

        string[] bcc = null;
        if (chkBcc.Checked)
            bcc = new string[] { user.Email };

        Dictionary<string, byte[]> fileBytes = new Dictionary<string, byte[]>();
        fileBytes.Add(manifest.ManifestNumber + ".pdf", bytes);

        EmailHelper.SendEmail(elm1.Value,
            new ConfigManager().GetString("Email From", null),
            emails.ToArray(),
            null,
            bcc,
            "Manifest",
            null,
            fileBytes);
    }

    protected void btnSendFax_Click(object sender, EventArgs e)
    {
        Dictionary<string, object> parms = new Dictionary<string, object>();
        parms.Add("Include Header", true);
        byte[] bytes = ManifestPdf.Generate(manifest, File.ReadAllText(Server.MapPath("~/Manifests/" + ManifestPdf.GetXmlFileName(manifest))), parms);

        string fax = ServiceHelper.ifNull(txtFax.Text).Replace(" ", "").Replace("-", "").Replace(".", "").Replace("(", "").Replace(")", "");
        string email = fax + new ConfigManager().GetString("Fax To", null);

        string from = new ConfigManager().GetString("Fax From", null);

        AbleUser user = AbleUser.FetchUserByUsername(Page.User.Identity.Name);

        Dictionary<string, byte[]> fileBytes = new Dictionary<string, byte[]>();
        fileBytes.Add(manifest.ManifestNumber + ".pdf", bytes);

        EmailHelper.SendEmail(elm1.Value,
            from,
            new string[] { email },
            null,
            null,
            "Manifest",
            null,
            fileBytes);
    }

    protected void btnEdit_Click(object sender, EventArgs e)
    {
        Response.Redirect("Detail.aspx?ManifestId=" + manifest.ManifestId + "&redirect=" + redirect);
    }

    protected void backButton_Click(object sender, EventArgs e)
    {
        Response.Redirect(redirect + ".aspx");
    }

    protected void btnCancel_Click(object sender, EventArgs e)
    {
        ObjectsRemoved r = new ObjectsRemoved();
        r.RemovedByUser = User.Identity.Name;
        r.RemovedTime = DateTime.Now;
        r.Category = "Manifest";
        r.Extra1 = manifest.ManifestNumber;
        r.Save();

        ChangeManager.TrackRemoved("Manifest Removed", manifest.ManifestId, manifest.ManifestNumber, manifest, User.Identity.Name, new System.Collections.Generic.List<string>());
        ManifestDetailCollection detail = manifest.Detail;
        foreach (ManifestDetail d in detail)
            ChangeManager.TrackRemoved("Manifest Detail Removed", d.DetailId, manifest.ManifestNumber, d, User.Identity.Name, new System.Collections.Generic.List<string>());

        ServiceHelper.UpdateSql("delete from able_ManifestNote where ManifestId=" + manifest.ManifestId);
        ServiceHelper.UpdateSql("delete from able_ManifestDetail where ManifestId=" + manifest.ManifestId);
        ServiceHelper.UpdateSql("delete from able_Manifest where ManifestId=" + manifest.ManifestId);
        //manifest.ManifestStatus = ManifestStatus.Cancel;
        //manifest.Save(User.Identity.Name);
        //Response.Redirect("View.aspx?ManifestId=" + manifest.ManifestId);

        List<PageHistory> history = (List<PageHistory>)Session["PAGE_HISTORY"];
        if (history != null && history.Count > 1)
        {
            int index = history.Count - 2;
            if (index > -1)
            {
                PageHistory page = history[index];
                Response.Redirect(page.Url);
                return;
            }
        }

        Response.Redirect(redirect + ".aspx");
    }

    protected void btnAudit_Click(object sender, EventArgs e)
    {
        Response.Redirect("~/Reports/Audit.aspx?s=" + manifest.ManifestNumber);
    }
}

Open in new window

Lakin ITAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
why not copy (or move) your code from btnPdf_Click and put it in it's own function, with a parameter for the ID. then wherever the IDs are coming from, put them in some kind of collection, such as an array, or list, or whatevers appropriate, loop through that collection, can call your newly created function with the ID as the parameter
0
Lakin ITAuthor Commented:
@BigMonty - that's exactly what I want to do, but need help with the syntax.
0
Lakin ITAuthor Commented:
This is the direction I'm heading - close?

    protected void createBatchPDFs(object sender, EventArgs e)
    {

        List string list_of_manifests = "1234, 1235, 1236";

        foreach (var manifestid in list_of_manifests)
        {

            Response.Clear();
            Response.Charset = "";

            Response.ContentType = "application/pdf";
            Response.AddHeader("Content-Disposition", "attachment; filename=\"" + manifest.ManifestNumber + ".pdf\"");

            Dictionary<string, object> parms = new Dictionary<string, object>();
            parms.Add("Include Header", true);
            byte[] bytes = ManifestPdf.Generate(manifest, File.ReadAllText(Server.MapPath("~/Manifests/" + ManifestPdf.GetXmlFileName(manifest))), manifestid);

            Response.OutputStream.Write(bytes, 0, bytes.Length);

            Response.Flush();
            Response.End();

        }

    }

Open in new window

0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
I'm a classic asp guy (where this was originally posted), with experience in vb.net.  c# is def not my strong suit, you may want to his "Request Attention" to get one of the mods to send an additional message to .NET experts
0
Lakin ITAuthor Commented:
Ok - I'll see if the mods can send to .NET.
0
Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
BM, you can obviously see this is not Classic ASP.  You answered as if you knew what you are talking about.  If you don't know the topic, then don't participate in it from the start and mislead people.
0
Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
Scott - I didn't mislead anyone. No one had answered the question in roughly 8 hours, so I took a stab at it, explaining the steps I would take. There was no mention of syntax in the original post, so I mis-understood it to be needing the logical steps to be thought out. Just because I mis-understood something doesn't mean i "misled" someone. Next time you want to attack my character, do so via private message. In the meantime, I've sent a message to an actual mod to come in and clean up your comments.

Lakin - I apologize for getting off topic above... From the very little of c# I do know, it looks like you're on the right track, however I think you'll want to move your Response.End to AFTER your foreach loop, otherwise you'll only process just one pdf doc.
0
Lakin ITAuthor Commented:
Thank you for your help, @BM.  FWIW, I didn't feel misled at all and appreciate the assistance - especially since yours has  been the only response to date.  I'm a CF dev and not entirely clear on .NET vs. .ASP, but was thinking mod's response was a little harsh to an attempt to help as well.
0
Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
Thx Lakin - much appreciated...

the difference between the 2 technologies is that classic asp is much more similar to php, since it is more of a scripting language, and .NET is more object oriented.

any luck with your code? are you getting any errors or is it just not working?
0
Lakin ITAuthor Commented:
I'm getting this error:  

CS1502: The best overloaded method match for 'Able.Data.ManifestPdf.Generate(Able.Data.Manifest, string, System.Collections.Generic.Dictionary<string,object>)' has some invalid arguments

Open in new window


On this line:

byte[] bytes = ManifestPdf.Generate(manifest, File.ReadAllText(Server.MapPath("~/Manifests/" + ManifestPdf.GetXmlFileName(manifest))), manifestid);

Open in new window


And this is what my function looks like now:

protected void createBatchPDFs(object sender, EventArgs e)
    {

        List<string> list_of_manifests = new List<string>();
        list_of_manifests.Add("12345");
        list_of_manifests.Add("67890");
        list_of_manifests.Add("13579");
        list_of_manifests.Add("24680");

        foreach (var manifestid in list_of_manifests)
        {

            Response.Clear();
            Response.Charset = "";

            Response.ContentType = "application/pdf";
            Response.AddHeader("Content-Disposition", "attachment; filename=\"" + manifest.ManifestNumber + ".pdf\"");

            Dictionary<string, object> parms = new Dictionary<string, object>();
            parms.Add("Include Header", true);
            byte[] bytes = ManifestPdf.Generate(manifest, File.ReadAllText(Server.MapPath("~/Manifests/" + ManifestPdf.GetXmlFileName(manifest))), manifestid);

            var uploadPath = Server.MapPath("~/_TEMP/PDF");
            var tempfilename = Guid.NewGuid().ToString();
            var tempfilenameandlocation = Path.Combine(uploadPath, Path.GetFileName(tempfilename));

            File.WriteAllBytes( tempfilenameandlocation, bytes);

            Response.Flush();

        }

            Response.End();

    }

Open in new window

0
Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
what is the data type for the variable manifestid? assuming you want it to be an INT, try changing your foreach statement to"

foreach (int manifestid in list_of_manifests)

Open in new window

0
Lakin ITAuthor Commented:
No luck there, but thank you for your help.  

I ended up reconstructing the function outside of the system in Coldfusion - so far so good.
0
Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
excellent, glad you got it working :)
0
_agx_Commented:
(no points...just an observation about the code)

>> Source comment
>> This is the direction I'm heading - close?

Without testing it, looks like that code attempts to return multiple files to a single http request. ie

              -- download 1234.pdf
              -- download 1235.pdf
              -- download 1236.pdf

You can't really do that with http. It's designed to return a single file per http request.

If you want to allow a user to download say 20 files, you either need to a) zip the 20 files into a single archive and download the .zip file -OR- possibly merge them into one big pdf (like with cfpdf action="merge". and download that file
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Lakin ITAuthor Commented:
I don't want to return multiple files per request - I know that's what the code looks like - I just didn't get rid of all of the Response stuff.

I simply wanted to loop a given list of manifest ID's and create a PDF for each one.  They didn't need to go to a browser session, just a local directory on disk.
0
_agx_Commented:
Gotcha.

I can't test any of this right now, but I'd go with the approach suggested earlier.  Create a method that generates a single pdf and saves it to a temp file:

protected string SavePDFToTempFile(int manifestID) {
    // lookup manifest by id first
    Manifest manifest = Manifest.FetchByID(manifestID);
    Dictionary<string, object> parms = new Dictionary<string, object>();
    parms.Add("Include Header", true);
    byte[] bytes = ManifestPdf.Generate(manifest, File.ReadAllText(Server.MapPath("~/Manifests/" + ManifestPdf.GetXmlFileName(manifest))), parms);

    // save bytes to temp file
    string uploadPath = Server.MapPath("~/_TEMP/PDF");
    string tempfilename = Guid.NewGuid().ToString();
    string tempfilenameandlocation = Path.Combine(uploadPath, Path.GetFileName(tempfilename));
    File.WriteAllBytes( tempfilenameandlocation, bytes);

    // return file path
    return tempfilenameandlocation ;
}

Open in new window


Then call that method within your loop. Note, it didn't seem like the id's were strings, so I changed the List type "int".

    List<int> list_of_manifests = new List<int>();
    list_of_manifests.Add(12345);
    list_of_manifests.Add(67890);
    list_of_manifests.Add(13579);
    list_of_manifests.Add(24680);

    foreach (int manifestid in list_of_manifests) 
    {
       string savedToFile = SavePDFToTempFile(manifestid);
       // maybe save the file names to an array here ...
      
    }

Open in new window

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.