i am using iframe tag in order to call ActionMethod that returns FileResult to display PDF file. The issue is after it loads PDF document instead of showing pdf file name, it shows ActionMethod name on the top of the PDF file name in Chrome.
Razor Code:
<iframe src="#Url.Action("GetAgreementToReview", "Employee")" style="zoom: 0.60; -ms-zoom: 1; width: 100%;" width="99.6%" height="420" frameborder="0" id="agreementPdf"></iframe>
CS Code:
public ActionResult GetAgreementToReview()
{
Response.AddHeader("Content-Disposition", "inline; filename=Master-Agreement.pdf");
return File("~/Content/Master-Agreement.pdf", "application/pdf");
}
Image: As you can see in the screenshot, it shows 'GetAgreementToReview' i.e. ActionMethod name instead of 'Master-Agreement.pdf'.
Does anyone know how to fix this issue?
Thanks.
Sanjeev
I had a similar problem and found a solution after exploring almost everything the web has to offer.
You must use a custom route for your action and you must send the filename from UI into the URL itself. (Other parameters won't be affected)
//add a route property
[Route("ControllerName/GetAgreementToReview/{fileName?}")]
public ActionResult GetAgreementToReview(string fileName, int exampleParameter)
{
byte[] fileData = null; //whatever data you have or a file loaded from disk
int a = exampleParameter; // should not be affected
string resultFileName = string.format("{0}.pdf", fileName); // you can modify this to your desire
Response.AppendHeader("Content-Disposition", "inline; filename=" + resultFileName);
return File(fileData, "application/pdf"); //or use another mime type
}
And on client-side, you can use whatever system to reach the URL.
It's a bit hacky, but it works.
If you have an Iframe on HTML to display the PDF (the issue I had), it could look like this:
<iframe src='/ControllerName/GetAgreementToReview/my file?exampleParameter=5' />
And this way you have a dynamic way of manipulate the filename shown by the IFRAME that only uses the last part of an URL for its name shown on the web page (quite annoying). The downloaded filename will have its name given from server-side Content-disposition.
Hope it helps !
please try this code :
return File("~/Content/Master-Agreement.pdf", "application/pdf", "filename.pdf");
Other Helper Link : Stream file using ASP.NET MVC FileContentResult in a browser with a name?
Related
Usually, in ASP.NET, MVC or otherwise, we make the client download a file by having the user click a link/button; I assume this link/button action goes to the correct controller then redirects back to the main page. However, how can I cause the download from some intermediate controller, during a series of redirects?
Basically, when the user clicks a button to create a PDF, the action goes to PdfController to create the PDF, then, since I'm assuming he/she wants to download the PDF anyway (if he/she doesn't, he/she can always click "No"), I want to have the browser download the PDF before the page gets rendered again. If I haven't lost you yet, how do I accomplish this?
Here's a sample of what I have so far. Button that starts the action:
<a class="btn btn-primary col-md-2 col-md-offset-1" href="#Url.Action("MakePdf", "Pdf")">Create PDF</a>
PdfController's MakePdf() method:
public ActionResult MakePdf()
{
string PdfUrl = Environment.GetEnvironmentVariable("HOMEDRIVE") + Environment.GetEnvironmentVariable("HOMEPATH") + "/Sites/Bems/PDF/UserPdfs/report" + Id + ".pdf";
// create the PDF at this PdfUrl
return RedirectToAction("ShowPdf", "Pdf", new { PdfUrl = PdfUrl });
}
PdfController's ShowPdf() method, redirected from the previous MakePdf() method:
public ActionResult ShowPdf(string PdfUrl)
{
if (System.IO.File.Exists(PdfUrl))
{
return File(PdfUrl, "application/pdf"); // Here is where I want to cause the download, but this isn't working
}
else
{
using (StreamWriter sw = System.IO.File.CreateText(PdfUrl))
{
sw.WriteLine("A PDF file should be here, but we could not find it.");
}
}
return RedirectToAction("Edit", "Editor"); // Goes back to the editing page
}
I'm trying to cause the download at the place in the code I specified, but I'm not sure how to cause it. Usually you return it somehow to the view, whereas here I'm calling an object, I think, but I'm really fuzzy on how that all works. Regardless, something I'm doing isn't working. Any ideas on what that is?
You can't return the ViewResult RedirectToAction("Edit", "Editor") and in the same response a FileResult File(PdfUrl, "application/pdf")
To accomplish your task you could follow this scenario:
click on button create pdf
call the RedirectToAction("Edit", "Editor");
in this case at the end of the view, add a javascript call to the action method returning the FileResult
once the page is rendered, the download will start automatically
I have some advanced users who need to see the raw XML of a transaction. I thought I could just have a link on the source page (with target="_blank") to a new page that would just output the XML using Response.Write, having set the Content-Disposition header to inline, and Response.ContentType to "text/xml".
That works nicely with FireFox and Chrome, but in IE10, I get the security warning about "Do you want to view only the webpage content that was delivered securely?"
Research shows that this message is displayed when the page contains "mixed content". That is, when some of the content is in "https", and some is in "http". That is not the case in my scenario, as the entire content is just the XML document, which doesn't even contain a reference to "http" in it.
I found several articles about this, and they suggest changing the page to use only https, or changing the IE security settings to "Enable" mixed content without prompting:
http://blog.httpwatch.com/2009/04/23/fixing-the-ie-8-warning-do-you-want-to-view-only-the-webpage-content-that-was-delivered-securely/
http://blogs.msdn.com/b/ieinternals/archive/2009/06/22/https-mixed-content-in-ie8.aspx
http://blog.httpwatch.com/2009/09/17/even-more-problems-with-the-ie-8-mixed-content-warning/
But, again, I have no "http" content on the "page"!
How can I display "raw" XML content in IE without this prompt?
I did this for an internal debugging app i made. It works in IE without any issues/popups. BUT, it's not really "raw XML", but more like xml -> html displayed in a div (still looks like XML though) as plain text. I made it using webapi, and also used angularjs, but you can change the angular to straight jquery.
Not sure if you're only after a straight up raw XML answer, but if you just want to display XML in text form, this should help you or at least give you some inspiration lol:
api action: returns xml through ajax. The webresponse().response = string that contains xml.
public HttpResponseMessage GetResponse(RequestDTO requestDTO)
{
return new HttpResponseMessage()
{
Content = WebResponse(requestDTO).Response
};
}
angular part:
$http.post('api/getresponse', requestData)
.success(function (data) {
$scope.response.xml = data;
});
html part:
<h3>XML Response</h3>
<pre highlight="response.xml" class="xml response"></pre>
Edit
To answer your questions:
"highlight" is a directive, and i think i originally made it because i was going to try and add code highlighting, but never did. But all it does is this:
angular.element(elem).text(value);
equivalent to the $(jquery).text(value); function.
As for the xml/response class, all it does is XDocument.Parse(xml), and return as new StringContent();
edited snippet from my code:
protected ResponseDTO WebResponse(RequestDTO requestDTO)
{
//....
var response = myRequest.GetXmlResponse(webResponse);
return new ResponseDTO()
{
Headers = new StringContent("....");
Response = new StringContent(response.ToString())
};
}
public XDocument GetXmlResponse(HttpWebResponse webResponse)
{
return XDocument.Parse(xmlResponse(webResponse, Encoding.UTF8));
}
the ajax is returned as Content-Type: text/plain; charset=utf-8
I'm having trouble with displaying image from db. I think that method for saving image is working, because I see in DB that varbinary fields have some value, and that image type is correct. Also the size of image. But when I want to display image for product i don't get anything. Just blank space.. here is my code...
public byte[] GetImage(int productID)
{
Product product = products.GetByID(productID);
byte[] imageData = product.ImageData.ToArray();
return imageData;
}
That code is in my controller. Second is code from view :
<% if (product.ImageData != null) { %>
<img src='/product/getimage/<%= Html.Encode(product.ID) %>' alt=""/>
<% } %>
I tried some solutions found here on stack overflow, and everyone do it like this, but it's working for them. I dont have any idea why images aren't displayed. When i look at source code of page at debugging i have :
<img src='/product/getimage/18' alt=""/>
I'm using .net 4.0, MVC 2, VS 2010... Thanks in advance
My guess is that you have a routing issue. If the url /product/getimage/18 should work for your action you need to have a route that looks something like this:
routes.MapRoute("ProductImage",
"product/getimage/{productID}",
new { controller = "Product", action = "GetImage", productID = "" }
);
To confirm this you should use firebug and check the "net" tab (or set a breakpoint in your action and see if it gets hit when you load the page).
I would also recommend using the build in helpers to generate your urls (then this kind of problem will never happen). Instead of src='/product/getimage/<%= Html.Encode(product.ID) %>' you can write src='<%=Url.Action("GetImage", "Product", new { productID = product.ID })%>'
I'm not much of an expert on MVC yet - but from what I can see, I think your GetImage function needs to be an Action Method inside your controller, so it'll need to return an ActionResult?
You'll probably need to set the Content-Type header in the response, too.
This guy looks like he knows what he's talking about...
http://blogs.msdn.com/miah/archive/2008/11/13/extending-mvc-returning-an-image-from-a-controller-action.aspx
Try to change you method to:
public void GetImage(int productID)
{
Product product = products.GetByID(productID);
Response.ContentType = "image/jpeg";
Response.BinaryWrite(product.ImageData.ToArray());
}
You have:
<img src='/product/getimage/18' alt=""/>
Normally i'd say an image tag looks like this:
<img src='/product/getimage/18.jpg' alt=""/>
I needed to register routes in my global.cs file like Mathias suggested.
Also i needed to modify action in my controller to this :
public FileContentResult GetImage(int productID)
{
Product product = products.GetByID(productID);
return File(product.ImageData.ToArray(), product.ImageMimeType);
}
I wish thank you all for your fast answers...
I am trying to add page with custom extension, say .asp2 with my set of html tags.
Now whenever i try to access the page on browser...it asks me "Save as". This happens because I am using an extn which the server is not able to recognise.
What should I do to so that my server, IIS 5.1 recognises this extension??
Please suggest
Also please suggest on how to associate custom events on such custom page?
In Internet Services Manager, right click on Default Web Site, select Properties, in Home Directory press the Configuration button. Click the Add button and fill the Executable field with the path to the aspnet_isapi.dll file and put asp2 in the Extension field.
Using a non-standard extension, you should also be sure to set the response's Content Type to text/html, so the browser knows how to interpret the document you're sending. Something like:
public class HttpHandler1 : IHttpHandler
{
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/html";
// Your code here.
}
}
I have an ASP.NET user control (.ascx file). In this user control I want to use a .js file.
So I include <script src="file.js" type"text/javascript"></script> on the page.
However, sometimes I use this user control in a webpage where this same script has already been loaded.
How can I add a <script /> declaration that will render on the page only if the page doesn't already contain another <script /> tag for the same script?
As you are using asp.net, it makes sense to do the check server-side as that will be where you choose to add the reference to the javascript file. From your .ascx file you could register with the following:
this.Page.ClientScript.RegisterClientScriptInclude("GlobalUnqiueKey", UrlOfJavascriptFile);
... from your page you just call the ClientScript object directly:
ClientScript.RegisterClientScriptInclude("GlobalUnqiueKey", UrlOfJavascriptFile);
The 'GlobalUniqueKey' can be any string (I use the url of the javascript file for this too)
If you try to register a script with the same key string, it doesn't do anything. So if you call this in your page, your control or anywhere else, you'll end up with only one reference in your page. The benefit of this is that you can have multiple instances of a control on a page and even though they all try to register the same script, it is only ever done a maximum of one time. And none of them need to worry about the script being already registered.
There is a 'IsClientScriptIncludeRegistered(stringkey)' method which you can use to see if a script has already been included under that key but it seems pretty redundant to do that check before registering as multiple attempts to register do not throw exceptions or cause any other errors.
Doing the check client-side means that, assuming the multiple javascript references are cached by the browser (they may not be), you still have multiple tags and the over head of each one causing some javascript to run. If you had 20 instances of your control on a page, you could get serious issues.
You can do one of two things client side...
Check the dom for the script tag corresponding to the javascript file your want to check
Test a variable or function you know has/will be defined within the javascript file for undefined.
Here's a quick JS function which uses JQuery to do what you need:
function requireOnce(url) {
if (!$("script[src='" + url + "']").length) {
$('head').append("<script type='text/javascript' src='" + url + "'></script>");
}
}
use something like the following:
if(typeof myObjectOrFunctionDecalredInThisScript != 'undefined') {
// code goes here
var myObjectOrFunctionDecalredInThisScript = { };
}
This tests if your object or function already exists and thus prevents redeclaration.
var storePath = [];
function include(path){
if(!storePath[path]){
storePath[path]= true;
var e = document.createElement("script");
e.src = path;
e.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(e);
return false;
} }
use this in your main page and call function include with argument javascript file name
As you want to include javascript on one page of your site only.
If you use Asp.net(4.0) then it is very easy.
Just include following code
<script type="text/javascript" scr="filepath and name here"></script>
in ContentPlaceHolder of content page.
#Shimmy I am coming across this after a long while but maybe it might still be useful or at least help other coming from behind. To check if jquery is already loaded do this
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.x.x.min.js"><\/script>')</script>
Don't miss the escape character in the closing script tag in document.write statement.
#mysomic, why did I not think of that. thumbs up
PS: I would have loved to write this right under the line where #Shimmy wrote that jQuery itself is the script he wants to load. But dont know how to write it there. cant see a reply or anything similar link. This may sound dumb but maybe I'm missing something. Pls point it out, anybody?
If you need it from server side, and Page.ClientScript.RegisterClientScriptInclude won't work for you in case script was included by some other way other then Page.ClientScript.RegisterClientScript (for example page.Header.Controls.Add(..), you can use something like this:
static public void AddJsFileToHeadIfNotExists(Page page, string jsRelativePath)
{
foreach (Control ctrl in page.Header.Controls)
{
if (ctrl is HtmlLink htmlLink)
{
if (htmlLink.Href.ToLower().Contains(jsRelativePath.ToLower())) return;
}
if (ctrl is ITextControl textControl
&& (textControl is LiteralControl || textControl is Literal))
{
if (textControl.Text.ToLower().Contains(jsRelativePath.ToLower())) return;
}
if (ctrl is HtmlControl htmlControl)
{
if (htmlControl.Attributes["src"]?.ToUpper()
.Contains(jsRelativePath.ToUpper())) return;
}
}
HtmlGenericControl Include = new HtmlGenericControl("script");
Include.Attributes.Add("type", "text/javascript");
Include.Attributes.Add("src", page.ResolveUrl(jsRelativePath));
page.Header.Controls.Add(Include);
}