Friday, June 6, 2014

Posting a form to get a file in return

I was working on an ASP.NET MVC application that, at some point, had to display the PDF version of an invoice. The file was stored on 3rd party's server and the only way you could get it was by posting a form. The form had to have an action (link) set and 2 inputs, one for the password and one for the username.

In order to achieve this, there are 2 possible solutions, but (in this case) only one (Solution 2) is the right solution.

So let's begin with the first solution.

Solution 1

First we write the html for the form:

    <form id="frmInvoice" method="post" target="_blank" >

        <input type="hidden" name="user" value="@Model.UserName" id="user" />

        <input type="hidden" name="pwd" value="@Model.Password" id="pwd" />

    </form>

Not so much to say here, just that the inputs for password and username are all hidden, meaning they will not appear in the web page.

Somewhere outside the form we create a button that will submit the form through a javascript function. We could have defined the button inside the form, but in this application it was not the case.

<input type="button" value="pdf" id="@Model.InvoiceNumber" onclick="postInvoiceForm(@Model.InvoiceNumber, '@Model.ActionLink');"  />


This button will call the javascript function below:

 function postInvoiceForm(invoiceNbr, actionLink) {

        var form = document.getElementById('frmInvoice');

        form.setAttribute('action', actionLink + invoiceNbr);

        form.submit();

    }


The 'action'  is the link where the form has to be posted, something like http://www.siteWithPdfs.com/pdfid. In order for the javascript function to work I had to put the value inside single quotes.

Problem

The problem with this approach is that the username and password are visible in the page if you look at the source. This is the reason I had to go with the second option.You could use this solution if you did not have any user and password, since it would be the fastest to implement.



Solution 2

Use WebRequest instead.

In the view change the button with:

<a href="@Url.Action("GetInvoicePDF", "MyController", new { invoiceNumber = Model.InvoiceNumber })" target = "_blank">

          <img src="@Url.Content("~/Content/images/filetype_pdf.png")" alt="pdf" />

 </a>

The target = _blank is set so that I get the pdf in a new tab (or window) and I don't loose the page I was coming from.

In the MyController controller, create the method GetInvoicePDF:

public ActionResult GetInvoicePDF (string invoiceNumber)

{

   WebRequest request = WebRequest.Create("www.siteWithPdfs.com");

   request.Method = "POST";

   request.ContentType = "application/x-www-form-urlencoded";

            

   Encoding iso8859_1 = Encoding.GetEncoding("iso-8859-1");

   StreamWriter sw = new StreamWriter(request.GetRequestStream(), iso8859_1);

   sw.Write("User=");

   sw.Write(HttpUtility.UrlEncode(Model.UserName, iso8859_1));

   sw.Write("Pwd=");

   sw.Write(HttpUtility.UrlEncode(Model.Password, iso8859_1));

   sw.Close();



Stream fs = request .GetResponse().GetResponseStream();

var fsResult = new FileStreamResult(fs, "application/pdf");

return fsResult;

}


The method creates a WebRequest object that will be used to post the form. The encoding was used only because I had to prepare for nordic characters.





No comments:

Post a Comment