c# - from - mvc partial javascript
¿Usando iTextSharp con JavaScript desactivado u otro framework MVC/MVVM? (1)
La pregunta se aplica a cualquier Marco de JavaScript que haga MVC
o MVVM
. Mencionado anteriormente:
Necesito pasar el DOM que se generó por knockout, como una cadena, a mi controlador C #, para poder construir el PDF.
Así que voy a ir con un simple ejemplo de trabajo para hacer esto en ASP.NET MVC. Nunca usé knockout.js
antes, así que voy a obtener el elemento DOM
y enviar la solicitud Ajax
con jQuery
.
La vista, basada en el ejemplo al que hizo referencia arriba: 1. Obtiene outerHTML
de ul
; 2. envía una solicitud de Ajax
al controlador:
<h4>People</h4>
<ul id=''wanted'' data-bind="foreach: people">
<li>
Name at position <span data-bind="text: $index"> </span>:
<span data-bind="text: name"> </span>
<a href="#" data-bind="click: $parent.removePerson">Remove</a>
</li>
</ul>
<button data-bind="click: addPerson">Add</button>
<button data-bind="click: getPdf">Get PDF</button>
@section scripts
{
<script src="~/Scripts/libs/knockout-3.4.0.js"></script>
<script src="~/Scripts/ajax/FileSaver.js"></script>
<script src="~/Scripts/ajax/jquery.binarytransport.js"></script>
<script src="~/Scripts/ajax/jquery-binary.js"></script>
<script type="text/javascript">
function AppViewModel() {
var self = this;
self.getPdf = function (data, event) {
$(this).downloadFile(
''@Url.Action("Index", "DomToPdf")'',
{ xHtml: $(''#wanted'').prop(''outerHTML'') }
);
}
self.people = ko.observableArray([
{ name: ''Bert'' },
{ name: ''Charles'' },
{ name: ''Denise'' }
]);
self.addPerson = function () {
self.people.push({ name: "New at " + new Date() });
};
self.removePerson = function () {
self.people.remove(this);
}
}
ko.applyBindings(new AppViewModel());
</script>
}
Notas:
- FileSaver.js no es técnicamente necesario, pero ahorra una gran cantidad de tiempo al no tener que lidiar con diferentes implementaciones de navegador. Referencia de compatibilidad del navegador .
- BinaryTransport es necesario si se usa
jQuery
. Desafortunadamente, el framework no admite esta función de manera predeterminada la última vez que lo verifiqué. Otros marcos comoAngularJS
admiten binarios. Referencia Envío y recepción de datos binarios .
jquery-binary.js
es un plugin jQuery
simple que escribí para un par de proyectos internos:
(function ($) {
$.fn.downloadFile = function(url, data, requestType) {
$.ajax({
url: url,
data: data,
type: requestType || ''POST'',
dataType: ''binary''
})
.done(function(data, textStatus, jqXHR) {
var type = jqXHR.getResponseHeader(''Content-Type'');
var filename = jqXHR.getResponseHeader(''Content-Disposition'');
filename = filename && filename.indexOf(''attachment'') > -1
? filename.replace(/(?:[^=])+=/, '''')
: ''file.bin'';
var blob = new Blob([data], { type: type });
saveAs(blob, filename);
})
.fail(function(jqXHR, textStatus, errorThrown) {
alert(errorThrown);
})
;
return false;
};
}(jQuery));
Y el controlador: 1. analiza la cadena HTML
con XMLWorkerHelper
; 2. devuelve el PDF.
[HttpPost] // some browsers have URL length limits
[ValidateInput(false)] // or throws HttpRequestValidationException
public ActionResult Index(string xHtml)
{
Response.ContentType = "application/pdf";
Response.AppendHeader(
"Content-Disposition", "attachment; filename=test.pdf"
);
using (var stringReader = new StringReader(xHtml))
{
using (Document document = new Document())
{
PdfWriter writer = PdfWriter.GetInstance(
document, Response.OutputStream
);
document.Open();
XMLWorkerHelper.GetInstance().ParseXHtml(
writer, document, stringReader
);
}
}
return new EmptyResult();
}
Te permitirá decidir cómo lidiar con los estilos en línea. ;)
Ok, ya que descubrí que puedo usar iTextSharp para generar un PDF, fui por esa ruta.
Lo tengo donde guardará HTML con formato básico en un PDF. Ese no es el problema.
Lo que necesito hacer ahora es tomar marcado con noqueo y usar el HTML resultante (es decir, el DOM) como mi cadena para pasar al método que crea el PDF.
Entonces, por ejemplo, tengo una tabla que se genera con knockout. Necesito pasar el DOM que se generó por knockout, como una cadena, a mi controlador C #, para poder construir el PDF.
Básicamente, si miras lo que se genera aquí:
http://knockoutjs.com/documentation/foreach-binding.html
Y si lee el Ejemplo 2 (genera tres viñetas), ilustra la generación de la que estoy hablando. En mi caso, me gustaría tomar los puntos de viñeta generados y pasarlos a mi controlador - HTML y todo - como una cadena, para que pueda guardarlos.
¿Alguna idea? Ni siquiera estoy seguro de dónde comenzar aquí, sinceramente.