How to send XML file to client in ASP.NET MVC - c#

In an ASP.NET MVC I have a database table. I want to have a button on some view page, if some user clicks that button I my application will generate XML file containing all rows in the database. Then the file containing XML should be sent to the client so that the user will see a download pop-up window.
Similarly I want to allow user to upload an XML file whose content will be added to the database.
What's the simplest way to let the user upload and download file ?
Thanks for all the answers
EDIT:
This is my approach:
public FileContentResult Download() {
if(model.Series.Count() < 1) {
byte[] content = new byte[0];
return new FileContentResult(content, "Series");
}
XmlSerializer serializer = new XmlSerializer(model.Series.FirstOrDefault().GetType());
MemoryStream xmlStream = new MemoryStream();
foreach (Series s in model.Series) {
serializer.Serialize(xmlStream, s);
}
byte[] content2 = new byte[xmlStream.Length];
xmlStream.Position = 0;
xmlStream.Read(content2, 0, (int) xmlStream.Length);
return File(content2, "Series");
}
Where model is DataContext. Howewer this does not work. When I try to download the data I get this error:
XML Parsing Error: junk after document element
Location: http://localhost:1399/Xml/Download
Line Number 7, Column 10:</Series><?xml version="1.0"?>
---------^

for download part, you could use FileStreamResult
This page has examples for upload and download; check it out.

An XML document can only have one top level element. After the end of the element, you cannot have anything else. It looks like after the "</Series>" element you have "<?xml version="1.0>", which is invalid.

Related

Get and Download pictures with AngleSharp

I started using Anglesharp for a Project, I need to get and download not only HTML but also images of the document.
I know that in the Document object there is a property called Images, but appearently it doesn't get all of them, I did a test on a YouTube page and got only one (repeated several times).
For example I'd like to get the thumbinail of the current video, and this seems to be inside a <meta> tag.
To be more precise, images are stored inside this kind of tags:
<meta content="https://i.ytimg.com/vi/hW-kDv1WcQM/hqdefault.jpg" property="og:image">
So I wonder if there is a way to select all the nodes/url of any image inside a page, no matter the tag used.
I don't think that QuerySelectorAll does work in this case, as this selects only one type of node.
You can try the sample code you find on github to verify that (I just changed the url with the YouTube one, and the selector too :D):
// Setup the configuration to support document loading
var config = Configuration.Default.WithDefaultLoader();
// Load the names of all The Big Bang Theory episodes from Wikipedia
var address = "https://www.youtube.com/watch?v=hW-kDv1WcQM&feature=youtu.be";
// Asynchronously get the document in a new context using the configuration
var document = await BrowsingContext.New(config).OpenAsync(address);
// This CSS selector gets the desired content
var cellSelector = "img";
// Perform the query to get all cells with the content
var cells = document.QuerySelectorAll(cellSelector);
// We are only interested in the text - select it with LINQ
var titles = cells.Select(m => m.TextContent);
Oh, shure, you can also add this to check that the Image property doesn't get the video thumbinails:
var Images = document.Images.Select(sl=> sl.Source).Distinct().ToList();
Any other method to select nodes based on the URL content? (like all of the urls ending with ".jpg", or ".png", etc.)
You can use the LINQ API to get all attributes that contains image URL in a page, like so :
.....
var document = await BrowsingContext.New(config).OpenAsync(address);
//list all image file extension here :
var fileExtensions = new string[] { ".jpg", ".png" };
//find all attribute in any element...
//where the value ends with one of the listed file extension
var result = from element in document.All
from attribute in element.Attributes
where fileExtensions.Any(e => attribute.Value.EndsWith(e))
select attribute;
foreach (var item in result)
{
Console.WriteLine(item.Value);
}

Convert a Word (DOCX) file to a PDF in C# on cloud environment

I have generated a word file using Open Xml and I need to send it as attachment in a email with pdf format but I cannot save any physical pdf or word file on disk because I develop my application in cloud environment(CRM online).
I found only way is "Aspose Word to .Net".
http://www.aspose.com/docs/display/wordsnet/How+to++Convert+a+Document+to+a+Byte+Array But it is too expensive.
Then I found a solution is to convert word to html, then convert html to pdf. But there is a picture in my word. And I cannot resolve the issue.
The most accurate conversion from DOCX to PDF is going to be through Word. Your best option for that is setting up a server with OWAS (Office Web Apps Server) and doing your conversion through that.
You'll need to set up a WOPI endpoint on your application server and call:
/wv/WordViewer/request.pdf?WOPISrc={WopiUrl}&type=downloadpdf
OR
/wv/WordViewer/request.pdf?WOPISrc={WopiUrl}&type=printpdf
Alternatively you could try and do it using OneDrive and Word Online, but you'll need to work out the parameters Word Online uses as well as whether that's permitted within the Ts & Cs.
You can try Gnostice XtremeDocumentStudio .NET.
Converting From DOCX To PDF Using XtremeDocumentStudio .NET
http://www.gnostice.com/goto.asp?id=24900&t=convert_docx_to_pdf_using_xdoc.net
In the published article, conversion has been demonstrated to save to a physical file. You can use documentConverter.ConvertToStream method to convert a document to a Stream as shown below in the code snippet.
DocumentConverter documentConverter = new DocumentConverter();
// input can be a FilePath, Stream, list of FilePaths or list of Streams
Object input = "InputDocument.docx";
string outputFileFormat = "pdf";
ConversionMode conversionMode = ConversionMode.ConvertToSeperateFiles;
List<Stream> outputStreams = documentConverter.ConvertToStream(input, outputFileFormat, conversionMode);
Disclaimer: I work for Gnostice.
If you wanna convert bytes array, then to use Metamorphosis:
string docxPath = #"example.docx";
string pdfPath = Path.ChangeExtension(docxPath, ".pdf");
byte[] docx = File.ReadAllBytes(docxPath);
// Convert DOCX to PDF in memory
byte[] pdf = p.DocxToPdfConvertByte(docx);
if (pdf != null)
{
// Save the PDF document to a file for a viewing purpose.
File.WriteAllBytes(pdfPath, pdf);
System.Diagnostics.Process.Start(pdfPath);
}
else
{
System.Console.WriteLine("Conversion failed!");
Console.ReadLine();
}
I have recently used SautinSoft 'Document .Net' library to convert docx to pdf in my React(frontend), .NET core(micro services- backend) application. It only take 15 seconds to generate a pdf having 23 pages. This 15 seconds includes getting data from database, then merging data with docx template and then converting it to pdf. The code has deployed to azure Linux box and works fine.
https://sautinsoft.com/products/document/
Sample code
public string GeneratePDF(PDFDocumentModel document)
{
byte[] output = null;
using (var outputStream = new MemoryStream())
{
// Create single pdf.
DocumentCore singlePDF = new DocumentCore();
var documentCores = new List<DocumentCore>();
foreach (var section in document.Sections)
{
documentCores.Add(GenerateDocument(section));
}
foreach (var dc in documentCores)
{
// Create import session.
ImportSession session = new ImportSession(dc, singlePDF, StyleImportingMode.KeepSourceFormatting);
// Loop through all sections in the source document.
foreach (Section sourceSection in dc.Sections)
{
// Because we are copying a section from one document to another,
// it is required to import the Section into the destination document.
// This adjusts any document-specific references to styles, bookmarks, etc.
// Importing a element creates a copy of the original element, but the copy
// is ready to be inserted into the destination document.
Section importedSection = singlePDF.Import<Section>(sourceSection, true, session);
// First section start from new page.
if (dc.Sections.IndexOf(sourceSection) == 0)
importedSection.PageSetup.SectionStart = SectionStart.NewPage;
// Now the new section can be appended to the destination document.
singlePDF.Sections.Add(importedSection);
//Paging
HeaderFooter footer = new HeaderFooter(singlePDF, HeaderFooterType.FooterDefault);
// Create a new paragraph to insert a page numbering.
// So that, our page numbering looks as: Page N of M.
Paragraph par = new Paragraph(singlePDF);
par.ParagraphFormat.Alignment = HorizontalAlignment.Center;
CharacterFormat cf = new CharacterFormat() { FontName = "Consolas", Size = 11.0 };
par.Content.Start.Insert("Page ", cf.Clone());
// Page numbering is a Field.
Field fPage = new Field(singlePDF, FieldType.Page);
fPage.CharacterFormat = cf.Clone();
par.Content.End.Insert(fPage.Content);
par.Content.End.Insert(" of ", cf.Clone());
Field fPages = new Field(singlePDF, FieldType.NumPages);
fPages.CharacterFormat = cf.Clone();
par.Content.End.Insert(fPages.Content);
footer.Blocks.Add(par);
importedSection.HeadersFooters.Add(footer);
}
}
var pdfOptions = new PdfSaveOptions();
pdfOptions.Compression = false;
pdfOptions.EmbedAllFonts = false;
pdfOptions.EmbeddedImagesFormat = PdfSaveOptions.EmbImagesFormat.Png;
pdfOptions.EmbeddedJpegQuality = 100;
//dont allow editing after population, also ensures content can be printed.
pdfOptions.PreserveFormFields = false;
pdfOptions.PreserveContentControls = false;
if (!string.IsNullOrEmpty(document.PdfProperties.Title))
{
singlePDF.Document.Properties.BuiltIn[BuiltInDocumentProperty.Title] = document.PdfProperties.Title;
}
if (!string.IsNullOrEmpty(document.PdfProperties.Author))
{
singlePDF.Document.Properties.BuiltIn[BuiltInDocumentProperty.Author] = document.PdfProperties.Author;
}
if (!string.IsNullOrEmpty(document.PdfProperties.Subject))
{
singlePDF.Document.Properties.BuiltIn[BuiltInDocumentProperty.Subject] = document.PdfProperties.Subject;
}
singlePDF.Save(outputStream, pdfOptions);
output = outputStream.ToArray();
}
return Convert.ToBase64String(output);
}

iTextSharp Input string was not in a correct format css error

I have been trying to get my MVC application te create pdf files based on MVC Views. I got this working with plain html. But i would also like to iclude my css files that i use for the browser. Now some of them work but with one i get the following error:
An exception of type 'System.FormatException' occurred in mscorlib.dll but was not handled in user code
Additional information: Input string was not in a correct format.
I am using the following code:
var data = GetHtml(new IndexModel(Context), "~\\Views\\Home\\Index.cshtml", "");
using (var document = new iTextSharp.text.Document())
{
//define output control HTML
var memStream = new MemoryStream();
TextReader xmlString = new StringReader(data);
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream("c:\\tmp\\my.pdf", FileMode.OpenOrCreate));
//open doc
document.Open();
// register all fonts in current computer
FontFactory.RegisterDirectories();
// Set factories
var htmlContext = new HtmlPipelineContext(null);
htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory());
// Set css
ICSSResolver cssResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(false);
cssResolver.AddCssFile(HttpContext.Server.MapPath("~/Content/elements.css"), true);
cssResolver.AddCssFile(HttpContext.Server.MapPath("~/Content/style.css"), true);
cssResolver.AddCssFile(HttpContext.Server.MapPath("~/Content/jquery-ui.css"), true);
// Export
IPipeline pipeline = new CssResolverPipeline(cssResolver, new HtmlPipeline(htmlContext, new PdfWriterPipeline(document, writer)));
var worker = new XMLWorker(pipeline, true);
var xmlParse = new XMLParser(true, worker);
xmlParse.Parse(xmlString);
xmlParse.Flush();
document.Close();
}
the string "data" is correct and has no issues, the problem lies with the AddCssFile().
If i create the pdf without and css files everything works, but including the css files triggers the error.
Help will be very much appreciated.
I don't know the exact answer, but by looking at the error you are getting back, I would try two different approaches.
Move the
cssResolver.AddCssFile(HttpContext.Server.MapPath("~/Content/elements.css"), true);
To something like
var cssPath = HttpContext.Server.MapPath("~/Content/elements.css"), true);
cssResolver.AddCssFile(cssPath);
Then set a breakpoint and look at the values being returned for cssPath. Make sure they are accurate and do not contain any odd characters.
Second approach... If all else fails, try giving an absolute URL to the CSS resource such as http://yourdomain.com/cssPath instead of a file system path.
If either of those two appraoches help you, then you can use it to determine the actual problem and then refactor it to your hearts content after that.
UPDATE ------------------------------------------------------------------>
According to the documentation, you need an absolute URL for the file, so Server.MapPath won't work.
addCssFile
void addCssFile(String href,
boolean isPersistent)
throws CssResolverException
Add a
Parameters:
href - the link to the css file ( an absolute uri )
isPersistent - true if the added css should not be deleted on a call to clear
Throws:
CssResolverException - thrown if something goes wrong
In that case, I would try using something like :
public string AbsoluteContent(string contentPath)
{
var path = Url.Content(contentPath);
var url = new Uri(HttpContext.Current.Request.Url, path);
return url.AbsoluteUri;
}
and use it like such :
var cssPath = AbsoluteContent("~/Content/embeddedCss/yourcssfile.css");

Saving Modified XML- WP8 C#

I've been trying to modify and save an xml dynamically. i've tried to find some answers but i didnt manage to.
i Succeeded to modify and change the xml data, but i encounter a problem with saving.
here is the code:
var resourceStreamInfo = Application.GetResourceStream(uri);
using (var stream = resourceStreamInfo.Stream)
{
doc = XDocument.Load(stream);
var Currencies = doc.Descendants("Currency");
XElement root = Currencies.Where(b => b.Element("ID").Value.IndexOf(CurrencyID, StringComparison.CurrentCultureIgnoreCase) >= 0).First();
root.SetElementValue("Rate", rate);
doc.Save(stream);
}
I understood that my stream is readonly, but what should I do?
From Application.GetResourceStreamI guess your are reading a file from your project bundle. You cannot modify it. You need to save the modified file to isolated storage

Creating excel document as attachment on a sharepoint list

I've got some problems adding a excel document as attachment on a custom list. I've made an eventreceiver which collects data from other lists and puts the data into an excel document.
What i've tried to do to correct the problem:
tested CreateContentRow(index, item) in a separate console application (works)
checked if theres something wrong with fetching information from other lists (works)
tried saving to a document library (the file gets saved without content)
tried to open the xlsx document to se if there's something wrong with the xml (no custom xml added).
The code works just fine, but the document is saved but it's identical to the template, no content added.
using (var memory = new MemoryStream())
{
var binary = template.OpenBinary();
memory.Write(binary, 0, binary.Length);
using (var document = SpreadsheetDocument.Open(memory, true))
{
var workbookPart = document.WorkbookPart;
var worksheetparts = workbookPart.WorksheetParts;
var worksheetpart = worksheetparts.FirstOrDefault();
var sheetData = worksheetpart.Worksheet.GetFirstChild<SheetData>();
var index = 2;
foreach (var item in items)
{
var row = CreateContentRow(index, item);
index++;
sheetData.AppendChild(row);
}
properties.ListItem.Attachments.Add("name" + string.Format("{0:yyyy-MM-dd_HHmmss}", DateTime.Now) + ".xlsx", memory.ToArray());
properties.ListItem.Update();
}
}
I'm using the same approach on another list where i generate .docx documents there it works just fine. Is there a big difference in how i should save the document depending on if its .xlsx or .docx ?
When i debug the cells and rows are added to the sheetdata, but it does not get saved. Any ideas on how to fix this ?
In order to get the content saved i needed to add save statements.
wspart.Worksheet.Save();
document.WorkbookPart.Workbook.Save();
When i added the lines above before adding the attachemnt everything worked as it should.

Categories