I have several <input>
fields on a page to collect user input. The page uses jQuery tabs. Once the user is finished inputting data they advance to the next jQuery tab until they are finally at the last tab which displays information retrieved via Ajax. The page never refreshes.
The above works fine, but now I am implementing an option where the user can convert the results to a PDF so they can save or print. Originally, the jQuery to trigger PDF conversion was:
$('#btnViewPrintSavePDF').click(function (event) {
event.preventDefault;
$(this).parents("form")
.attr("method", "POST")
.attr("action", "/Controller/ConvertToPDF");
.submit();
});
In the Controller:
[HttpPost]
public ActionResult ConvertToPDF()
{
object model = null;
ViewDataDictionary viewData = new ViewDataDictionary(model);
viewData.Add("MyValue1", Request["MyValue1"]);
viewData.Add("MyValue2", Request["MyValue2"]);
viewData.Add("MyValue3", Request["MyValue3"]);
// The string writer where to render the HTML code of the view
StringWriter stringWriter = new StringWriter();
// Get the base URL
String currentPageUrl = this.ControllerContext.HttpContext.Request.Url.AbsoluteUri;
String baseUrl = currentPageUrl.Substring(0, currentPageUrl.Length - "Controller/PDFTemplate".Length);
viewData.Add("BaseUrl", baseUrl);
// Render the Index view in a HTML string
ViewEngineResult viewResult = ViewEngines.Engines.FindView(ControllerContext, "PDFTemplate", null);
ViewContext viewContext = new ViewContext(
ControllerContext,
viewResult.View,
viewData,
new TempDataDictionary(),
stringWriter
);
viewResult.View.Render(viewContext, stringWriter);
// Get the view HTML string
string htmlToConvert = stringWriter.ToString();
// Create a HTML to PDF converter object with default settings
HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter();
// Set license key
htmlToPdfConverter.LicenseKey = "...hidden...";
// Convert the HTML string to a PDF document in a memory buffer
byte[] outPdfBuffer = htmlToPdfConverter.ConvertHtml(htmlToConvert, baseUrl);
// Send the PDF file to browser
FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");
fileResult.FileDownloadName = "MyPDF.pdf";
return fileResult;
}
Again, the above code works fine. The PDF conversion of a .cshtml view occurs and I am prompted with the usual dialog box asking if I want to open the PDF or save it.
Note that the original page never gets refreshed and that's the way it needs to remain.
THE PROBLEM:
I have a Json object/string that gets created in the original page. It needs to be submitted to the above ConvertToPDF()
routine along with all of the form fields (checkbox, text, etc). I can't figure out how to do this.
Ajax breaks ConvertToPDF()
in that the dialog box no longer pops up asking if you want to Open or Save the PDF.
My intention is to include the following code in ConvertToPDF()
:
GroupChoiceIds GroupChoiceIds = null;
if (Request["GroupChoiceIds"] != null)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
GroupChoiceIds = jss.Deserialize<GroupChoiceIds>(Request["GroupChoiceIds"]);
}
The above code snippet works elsewhere in my application using an Ajax POST like this:
$.ajax({
type: "POST",
url: "/Central/ConvertToPDF",
dataType: "json",
data: {
GroupChoiceIds: ('{ 'Key1' : 'Value1', 'Key2' : 'Key2', 'Key3' : 'Value3','SpecialKey1' : 'Special_|_Value' }')
},
....
});
So, how can I submit the GroupChoiceIds
Json string to ConvertToPDF()
without causing a page refresh and not breaking the Open/Save functionality?
EDIT
I've tried placing the Json string in a hidden <input>
field, but the field doesn't get submitted and doesn't show up in the Controller after form submission. The input field looks like this:
<input type="hidden" value="{ 'Key1' : 'Value1', 'Key2' : 'Value2', 'Key3' : 'Value3', 'SpecialKey' : 'Special_|_Value' }" id="GroupChoiceIds">
Apparently value= contains invalid characters, but I'm not sure which ones. Is there standard way of getting this Json string to be valid for use in a hidden value= attribute?
UPDATE
I was unable to add a hidden input field to the .cshtml and have it available in the controller no matter what I tried. Then I used @Html.Hidden("GroupChoiceIds")
and it worked. I'm confused by this - why can't I manually add a hidden input field? The controller function doesn't have a model specified and I assume it will accept/detect any input field submitted by the view?
I don't mind using @Html.Hidden (it works!) but I just wanted to learn why I am having to do it this way. Can somebody tell me what the difference is between:
<input id="GroupChoiceIds" type="hidden" value="" />
and
@Html.Hidden("GroupChoiceIds")