Display dynamic header using Rotativa pdf in MVC - asp.net-mvc

I wanted to print header data which are dynamic and will come from controller.
So how can I display that dynamic data in header using Rotativa pdf.
My header data include Name, Address, Contact info and other additional information, which are dynamic and generated from controller side.
I have created pdf with static header as below by using html page
string header = Server.MapPath("~/Static/NewFolder/PrintHeader.html");
string footer = Server.MapPath("~/Static/NewFolder/PrintFooter.html");
string customSwitches = string.Format("--header-html \"{0}\" " +
"--header-spacing \"0\" " +
"--footer-html \"{1}\" " +
"--footer-spacing \"10\" " +
"--footer-font-size \"10\" " +
"--header-font-size \"10\" ", header, footer);
return new ViewAsPdf("SchedulePrintPdf", modelData)
{
CustomSwitches = customSwitches,
PageOrientation = Orientation.Portrait,
PageMargins = { Top = 20, Bottom = 22 },
SaveOnServerPath = filePath, FileName = Path.GetFileName(fileName)
};
This is working well with Static header.
Now I need the header text will go from this controller dynamically.

I had a similar specification once and realized it with an extra View for Printing.
There you can get additional data from the controller and include a special CSS style.
When you use bootstrap, consider that the resolution used for PDF-printing is very small, so you have to use the col-xs-* classes.
In my case the Print-View was called ResultPrint.cshtml and in the Controller I had this function:
public ActionResult GeneratePDF(int id)
{
InputPrintModel model = db.InputPrintModel.Find(id);
if (model == null)
{
return HttpNotFound();
}
try
{
return new ViewAsPdf("ResultPrint", model);
}
catch (Exception ex)
{
// Error Dialog + Logging
return View("Result", model);
}
}
which was called in my Result.cshtml like this:
#Html.ActionLink("Generate PDF", "GeneratePDF", new { id = Model.Id })
EDIT
When you look at this answer https://stackoverflow.com/a/26544977/2660864 you can see, that you can use .cshtml files in your CustomActions (I did not test this code)
public ActionResult ViewPDF()
{
string cusomtSwitches = string.Format("--print-media-type --allow {0} --footer-html {0} --footer-spacing -10",
Url.Action("Footer", "Document", new { area = ""}, "https"));
return new ViewAsPdf("MyPDF.cshtml", model)
{
FileName = "MyPDF.pdf",
CustomSwitches = customSwitches
};
}
[AllowAnonymous]
public ActionResult Footer()
{
// get custom data for view
return View(model);
}

Related

The controller for path " " was not found or does not implement IController. error

I pull the tags in the news details section. The corresponding code block is below.
NewsDetail:
foreach (var item in etiketler.Take(1))
{
<span>#item</span>
}
foreach (var item in etiketler.Skip(1))
{
<span>#item</span>
}
Controller :
public ActionResult Tag(string tag, int? pageSize)
{
string id = this.RouteData.Values["tag"].ToString();
SectionServices _sectionServices = new SectionServices();
if (!pageSize.HasValue) pageSize = 1;
ViewBag.Current = pageSize;
Models.TagModel model = new Models.TagModel();
var dat = _sectionServices.getNewsByTag((int)pageSize, tag);
ViewData["etiket"] = tag;
if (dat != null)
{
ViewBag.Tag = tag;
model.getNews = dat;
return View(model);
}
return View();
}
Route Config :
routes.MapRoute(
name: "TagPage",
url: "{tag}-haberleri/{pageSize}",
defaults: new { controller = "Page", action = "Tag", pageSize = UrlParameter.Optional }
);
I get errors like "The controller for path '/Mert Hakan_haberleri / 2' was not found or does not implement IController" in log records. what is the cause of this error, clicking on tags works correctly, but I see this error in log records.
I also had this error. When I embedded the classes into a namespace, everything started working for me.
namespace PageControllers { // added this line!
public class PageController {
public ActionResult Tag() {
//code logic
return View();
}
}
}

MVC Image - Dispaly in a Tab instead of downloading to a file

I have the following controller method which gets a PNG from a web api.
public async Task<ActionResult> RealTimeUpdate(string fundName)
{
string docPath = ConfigurationManager.AppSettings["RealTimeUpdate"].Replace("{fundname}",fundName).ToString();
docPath = docPath.Replace("\\\\", "\\");
docPath = docPath.Replace("\"", "");
string url = ServiceUrl + "api/RealTime/" + fundName;
HttpResponseMessage response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var dataStream = response.Content.ReadAsStringAsync().Result;
if (dataStream == null)
return HttpNotFound();
var _buffer = JsonConvert.DeserializeAnonymousType(dataStream, new { _buffer = (byte[])null })._buffer;
// If user decides to save the file, this will help...
//Response.AddHeader("content-disposition", "filename=" + Path.GetFileName(path));
return File(_buffer, "application/png");
}
return View("Error");
}
I call it like this:
Real Time Update
As you can see, I have target="_blank", however, instead of displaying the image in a new tab, it downloads it to my documents folder. How can I get it to display in a tab?
You need a ImageController to render that.
once you have a controller you can render as follows:
public class ImageController{
public ActionResult ShowImage(string path)
{
return File(path);
}
}
in your views:
<img src="#Url.Action("Render","Image", new {id =1 // or path })" />
this answer was taken from https://stackoverflow.com/a/16142574/5586581

Iframe Src from controller

I have an Iframe in a view that i need to populate the src from my controller This is the part of the controller that it has to be called from.
else
{
//TODO: add after mobile detection is added back in
//if (Request.Browser.IsMobileDevice)
// return RedirectToAction("Index", "Mobile", new { Area = "" });
//else
return RedirectToAction("Index", "Home", new { Area = "" });
}
I know this is how youwould do it if it wasnt in MVC so how could i call my iframe from the controller?
ifr1.Attributes["src"] = "http://localhost:8000/index.php/login/?u=" + Session["username_s"] + "&p=" + Session["password_s"];
enter code here
You can use ViewData or ViewBag for this purpose.
In your controller you should have the following:
else
{
//TODO: add after mobile detection is added back in
//if (Request.Browser.IsMobileDevice)
// return RedirectToAction("Index", "Mobile", new { Area = "" });
//else
ViewBag.IframeUrl = "http://localhost:8000/index.php/login/?u=" + Session["username_s"] + "&p=" + Session["password_s"];
return RedirectToAction("Index", "Home", new { Area = "" });
}
In you View you can use the following:
<iframe src="#(ViewBag.IframeUrl)"></iframe>
You can also use ViewData by replacing ViewBag.IframeUrl with ViewData["IframeUrl"]
You should use ViewBag in the target action, passing the URL, for exemple:
1) Your target redirect action should look like:
public ActionResult Index()
{
//Other code from the action here
ViewBag.IFrameSrc = "http://localhost:8000/index.php/login/?u=" + Session["username_s"] + "&p=" + Session["password_s"];
return View();
}
2) The Index View should look like:
<iframe src="#ViewBag.IFrameSrc">
</iframe>

Error in displaying ckeditor in MVC

In my MVC application I want to display the extracted text in CKEDITOR.
but the text is getting diplayed in textarea and not in editor
My controller code is:
public ActionResult ExtractText(string fn)
{
string extFile = Server.MapPath(_fileUploadPath + fn);
string filePath = Path.Combine(HttpContext.Server.MapPath(_fileUploadPath), Path.GetFileName(fn));
if (filePath != null)
{
SautinSoft.PdfFocus f = new SautinSoft.PdfFocus();
f.OpenPdf(System.IO.File.ReadAllBytes(filePath));
string text = f.ToText();
string sValue = "<textarea id = \"temp_edit\" name=\"content\" cols=\"73\" rows=\"15\">" + text + "</textarea> <script type=\"text/javascript\">CKEDITOR.replace('temp_edit');</script><input class=\"margin-top-05 green_button\" type=\"button\" value=\"Save\" onclick=\"save_file()\" /><a class=\"close\" onclick=\"parent.$.fancybox.close();\"><img class=\"close_image\" title=\"close\" src=\"../images/closelabel.gif\" style=\"width: auto; height: auto; position: absolute; bottom: 0px; right: 0px;\"></a>";
return Content(sValue);
}
else
{
TempData["UploadValidationMessage_Failure"] = "File does not exist";
return View();
}
}
The textarea styles, javascript events can be done on your view. Pass the text to the view and show it on the textarea. All your events and styles can be written on the view. The ckeditor can be loaded to the textarea on ready function. Please go through the following.
CK Editor for .Net MVC
For a better way to implement CKEditor in your project, please go through the aswer in the following link
CKEditor MVC 3 implementaion Help needed
Edit..
<%= Html.ActionLink("Extract Text", "ExtractText", new { fn = file })%>
takes you to your function.
Lets say, you have a model NewContent
public class NewContent
{
public string Text
{
get;
set;
}
}
Return the NewContent object with you text from the controller.
public ActionResult ExtractText(string fn)
{
string extFile = Server.MapPath(_fileUploadPath + fn);
string filePath = Path.Combine(HttpContext.Server.MapPath(_fileUploadPath), Path.GetFileName(fn));
if (filePath != null)
{
SautinSoft.PdfFocus f = new SautinSoft.PdfFocus();
f.OpenPdf(System.IO.File.ReadAllBytes(filePath));
string text = f.ToText();
NewContent content = new NewContent();
content.Text = text;
return View(content);
}
else
{
TempData["UploadValidationMessage_Failure"] = "File does not exist";
return View();
}
}
In your view, add the following
<script src="ckeditor/ckeditor.js"></script>
<script src="ckeditor/adapters/jquery.js"></script>
<%=Html.TextAreaFor(c => c.Text) %>
<script type="text/javascript">
$(function () {
$('#Text').ckeditor();
});
</script>
You will get your text from controller in the view in a ck editor. Make sure you have all necessary ckeditor scripts and its location provided correctly

Rotativa Download with SaveAs dialog

I am using Rotativa tool to display pdf. It works fine with the following code:
public ActionResult PreviewDocument()
{
var htmlContent = Session["html"].ToString();
var model = new PdfInfo { Content = htmlContent, Name = "PDF Doc" };
return new ViewAsPdf(model);
}
I wanted to know the way to download the pdf via browser's "save as" dialog on clicking on a button and not to display in some iframe. "new ViewAsPdf(model)" just returns the pdf data.
Thanks in advance.
You can add additional attributes to the Rotativa call like this:
return new PartialViewAsPdf("PreviewDocument", pdfModel)
{
PageSize = Size.A4,
FileName = "PDF Doc.pdf"
};
And it'll create the file for you. :)
I finally got a way to do this.
Actually rotativa's method "return new ViewAsPdf(model)" returns HttpResponseStream. Where we can hardly do something. But we can modify/alter the response once the action get executed by using custom attribute. We can override OnResultExecuted() method of action filter.
Controller's action
[HttpGet]
[ActionDownload] //here a custom action filter added
public ActionResult DownloadDocument()
{
var htmlContent = "<h1>sachin Kumar</hi>";
var model = new PdfInfo {FtContent = htmlContent, FtName = "Populate Form"};
return new ViewAsPdf(model);
}
Custom Action filter:
public class ActionDownloadAttribute : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
//Add content-disposition header to response so that browser understand to download as an attachment.
filterContext.HttpContext.Response.AddHeader("content-disposition", "attachment; filename=" + "Report.pdf");
base.OnResultExecuted(filterContext);
}
}
You can use return new ActionAsPdf. No custom attributes or anything else required.
Example: https://github.com/webgio/Rotativa/
public ActionResult PrintPreviewDocument()
{
return new ActionAsPdf("PreviewDocument") { FileName = "PDF Doc.pdf" };
}
public ActionResult PreviewDocument()
{
var htmlContent = Session["html"].ToString();
var model = new PdfInfo { Content = htmlContent, Name = "PDF Doc" };
return View(model);
}

Resources