ASP.NET MVC FileContentResult inline PDF filename not showing in browser title - c#

.NET Framework 4.7.2 MVC project
I have a controller action that dynamically loads a PDF to return inline to the browser. Everything is working, except the filename is not showing in the browser title bar or the tab. Instead, the browser is showing the value of the "id" parameter, presumably because it follows the last slash.
I need the browser to display the PDF filename, so that users will know what PDF they are viewing. Our users tend to have multiple PDFs open in tabs and switch between them frequently. This is a simplified version of the code:
public FileContentResult ViewPDF(int id)
{
byte[] pdfContents = loadPDF(id);
string filename = getPDFFilename(id);
var cd = new ContentDisposition
{
FileName = filename,
Inline = true
};
Response.AddHeader("Content-Disposition", cd.ToString());
string returnContentType = MimeMapping.GetMimeMapping(filename);
return File(pdfContents, returnContentType);
}
I have also tried a FileStream with no luck and have tried Edge, IE, and Chrome, but they all do the same. In Chrome, when I Save the PDF, it does save with the correct filename but just won't show it in the browser.

This isn't the ideal solution, but I ended up creating a new View page that contains a full-screen <iframe> that loads the PDF inline. This way I could at least display the PDF name in the page title, which appears in the tab.
Similar to this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>#ViewData["Title"]</title>
<style type="text/css">
body, html {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
}
.pdfFrame {
width: 100%;
height: 100%;
border: none;
}
</style>
</head>
<body class="nomargins">
<iframe class="pdfFrame" src="#Url.Action("GetPDF", new { id = ViewBag.pdfID })" frameBorder="0"></iframe>
</body>
</html>

Related

How to embed the right url to custom font in HTML string

How to embed the right url to custom font in my HTML string.
I do the following:
string exeFile = (new System.Uri(Assembly.GetEntryAssembly().CodeBase)).AbsolutePath;
string path4 = Path.Combine(Regex.Escape(exeDir), "\\..\\\\..\\\\CSS\\\\majalla.ttf");
string arabicFont = #"#font-face {
font-family: 'sakkal_majallaregular';
src: url(" + "'" + path4 + "'" + #"), url('majalla-webfont.woff2') format('woff2'), url('majalla-webfont.woff') format('woff');}";
This doesn't work(doesn't take effect). After debugging path4 =
C:\\Users\\AA\\Desktop\\PrintingStatement\\PrintingStatement\\bin\\Debug\\..\\..\\CSS\\majalla.ttf
When I try the constant absolute url like this:
url('C:\\Users\\AA\\Desktop\\PrintingStatement\\PrintingStatement\\CSS\\majalla.ttf')
It works fine. How to convert my url to the previous one in production environment.
MY Updated HTML Method
protected string StyleStatementDoc(SingleStatement statementToPrint)
{
string path1 = "CSS/StatementVerifacation.css";
string path2 = "CSS/Statement.css";
string path3 = "CSS/print.min.css";
string path4 = "CSS/majalla.ttf";
string arabicFont = #"#font-face {
font-family: 'sakkal_majallaregular';
src: url(" + "'" + path4 + "'" + #"), url('majalla-webfont.woff2') format('woff2'), url('majalla-webfont.woff') format('woff');
}";
string htmlData = #"<!DOCTYPE html>
<html>
<head>
<title>Statement</title>
<style>" + arabicFont + #"
body {
font-size: 20px;
background-color: White;
color: Black;
font-family:'sakkal_majallaregular', Arial, Helvetica, sans-serif;
text-align:right;
direction:rtl;
}
p {
line-height: 32px; /* within paragraph */
margin-bottom: 30px; /* between paragraphs */
}
</style>
<link href = '" + path1 + "'" + " rel='stylesheet' />" + #"
<link href = '" + path3 + "'" + " rel='stylesheet' />" + #"
</head>
<body>
<div class='my' id='editor1'>" + statementToPrint.StatementBeforePrint + #"
</div>
</body>
</html>
";
// htmlData = htmlData.Replace(#"<head>", $#"<head><base href=""{new Uri(Application.StartupPath)}/""/>");
return htmlData;
}
System.Windows.Forms.WebBrowser webBrowser = new System.Windows.Forms.WebBrowser();
protected void Print(string htmlData)
{
webBrowser.SetHtmlContent(htmlData, $#"{new Uri(Application.StartupPath)}/");
webBrowser.Print();
}
My project structure:
To resolve relative addresses you have the following options:
Using a placeholder in html and replace it with bin folder address. (Works for everything but fonts)
Injection <base> tag in head. (Works for everything but fonts)
Implementing IMoniker to set base url for document. (Works for everything as well as fonts) I've implemented an extension method for WebBrowser1.SetHtmlContent(html, url)
Example
Assuming you have an html like this:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<title>Sample</title>
<style>
#font-face {
font-family: "MyFont";
src: url('./Contents/MyFont.ttf') format('truetype');
}
body {
background-image: url('./Contents/Image.jpeg');
font-family: 'MyFont';
font-weight: normal;
font-style: normal;
font-size: 30px;
color: red;
}
</style>
</head>
<body>
Something
</body>
</html>
I assume you have Contents folder containing Image.jpeg and MyFont.ttf files in your project output directory. (If you have them in your project, them in your project, to copy them into output directory into the right folder structure, just in the properties window of those files in solution explorer, set Copy to output directory to Copy Always.)
Solution 1 - use a placeholder in HTML file and replace it with bin path
So instead of ./ use $ROOT$/, for example: background-image:url('$ROOT$/Resources/Sample.jpeg'); Then when setting document text of the browser, replace it with start up path of the application:
this.webBrowser1.DocumentText = yourHtmlContent.Replace("$ROOT$",
new Uri(Application.StartupPath).ToString());
Solution 2 - Injectting html <base> tag
Assuming you don't have any placeholder in the html content. Then it's enough to inject a <base> tag into <head> like this:
var html = System.IO.File.ReadAllText("HTMLPage1.html");
html = html.Replace(#"<head>", $#"<head><base href=""{new Uri(Application.StartupPath)}/""/>");
webBrowser1.DocumentText = html;
It means all the relative addresses will be resolved using <base> href attribute.
Solution 3 - Implemeting IMoniker
You can implement IMoniker interface and using IWebBrowser2 from SHDocVw load the html content and set a base url for that. I used this method for relative address of #font-face as well as relative address for other stuff in html content and it worked well.
You find an Implementation which I shared in this post: Set URL of custom HTML loaded in webbrowser and easily use it like this:
webBrowser1.SetHtmlContent(html,
$#"{new Uri(Application.StartupPath)}/");

How can I center a image in a HTML created by HtmlAgilityPack

I have a very simple HTML document created with the HtmlAgilityPack, with a embedded image; (base64 format)
Public Report As New HtmlDocument()
Dim html As String = "<!DOCTYPE html>
<html>
<body>
<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANUAAADICAIAAADwajORAAAAAXNSR0IArs4c6QAAAARn"" alt=""Red dot"" align=""middle""/>
</body>
</html> "
Report.LoadHtml(html)
WebBrowser1.DocumentText = Report.Text
The image displays on the left, I'd like to horizontally center it, how can this be done?
(The actual base64 image is shortened for obvious reasons)
The answer I was looking for was:
With the HtmlAgilityPack you can embed the CCS insite the HTLM like so:
Dim html As String = "<!DOCTYPE html>
<html>
<body>
<head><style>html, body {
height: 100%;
margin:0;
padding:0;
}
.center {
display: block;
margin-left: auto;
margin-right: auto;
}
</style></head>
<div>
<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANUAAADICAIAAADwajORA"" alt=""Red dot"" class=""center""/>
</div>
</body>
</html> "
Thanks to Mortb for pointing me in the right direction.
give the image style of
img{
display:block;
margin:auto;
}
or you can put the image inside a div tag and give the div this style:
div{
width:; ==> give it any width you want
height:; ==> give it any height want
margin:auto;
}
In HTML images behave like text, so to center an image horizontally all you really need to do is add a div around it which centers all text:
<div style="text-align: center">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANUAAADICAIAAADwajORAAAAAXNSR0IArs4c6QAAAARn" alt="Red dot"/>
</div>
No special CSS workarounds needed.

Highlight 2 places in a single map without using search box [duplicate]

This question already has answers here:
Add "Search Area" outline onto google maps result
(5 answers)
Closed 5 years ago.
I want to highlight 2 places in google maps like the image below(could not show two places highlighted, i have just shown the border style that i will implement).
I want to show border of place exactly like the image below.
I want to dynamically mark places based on place name.
For example I don't have lat long values so ,so I have to search by name of
place.
Right now, to do this using the Google Maps Javascript API, you'll need external data to show the borders of each place. Having it internal to the Javascript API is already being requested here in Google's Issue Tracker: https://issuetracker.google.com/issues/35816953
As a workaround though, you can use the Maps Embed API to mimic the behavior you outlined in your post.
Here's a sample:
Be sure to replace YOUR_API_KEY_HERE with your own API key.
var input = document.getElementById('location');
var autocomplete;
function initPlaces() {
autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.addListener('place_changed', function() {
var place = autocomplete.getPlace();
if (!place.geometry) {
alert('Error with your search for ' + place.name);
}
if(place.place_id) {
markLocation(place.place_id);
}
})
}
function markLocation(placeId) {
var url = 'https://www.google.com/maps/embed/v1/place?key=AIzaSyCD0rWgXRVBa7PgaTWXVp_gU51pgHGviYY';
var placeStr = '&q=place_id:';
var iframe = document.getElementById('iframe');
placeStr += placeId;
url += placeStr;
iframe.src = url;
}
var onSubmitHandler = function(e) {
e.preventDefault();
//markLocation();
}
document.getElementById('form').addEventListener('submit', onSubmitHandler);
input {
height: 2rem;
border-radius: 2px;
border-style: none;
border: 1px solid #e2e2e2;
padding-left: 1rem;
}
.places {
height: 100px;
}
#map {
height: 100%;
}
#location {
width: 400px;
}
.map-frame {
width: 100%;
height: 500px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="places">
<form id="form" autocomplete="off">
<input id="location" type="text" placeholder="Enter a location">
</form>
</div>
<div class="map-frame">
<!-- Be sure to replace YOUR_API_KEY_HERE with your actual API key -->
<iframe width="100%" id="iframe" height="100%"frameborder="0" style="border:0"
src="https://www.google.com/maps/embed/v1/place?q=place_id:ChIJ-QB6d6K5lzMRxi-hKfTINm0&key=YOUR_API_KEY_HERE" allowfullscreen></iframe>
</div>
<!-- Be sure to replace YOUR_API_KEY_HERE with your actual API key -->
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY_HERE&libraries=places&callback=initPlaces" async defer></script>
</body>
</html>
An external jsbin link here as well if you want to try it out: jsbin
Here's the documentation of the Maps Embed API in case you want to pursue that track: https://developers.google.com/maps/documentation/embed/start
Hope that helps!

WPF Webbrowser create html file from user input

I'm reading a html using the webbrowser component in WPF. I should let the user to give there own text, upload an image and save it as a .html file.
By this way I can get the tag value:
string myTagValue = (FrameWithinGrid.Document as mshtml.HTMLDocument)
.getElementsByTagName("div")
.OfType<mshtml.IHTMLElement>()
.First()
.innerText;
How can i get the value from a text box and save it as a .html file including a new image?
Need your help. Thank you.
This is the html file:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>Welcome to Linguini Party!</title>
<style type="text/css">
* {
margin: 0;
}
html, body {
height: 100%;
font-family: Arial;
background-color: #e1dfe3;
color: #333333;
background-repeat: no-repeat;
}
h1 {
margin-right: 8%;
margin-left: 7%;
font-size: 450%;
text-align: center;
}
h2 {
font-size: 450%;
text-align: center;
color: #8a00ca;
font-style: italic;
}
</style>
</head>
<body id="Imagebg" background="welcome_final1.png">
<div id="container">
<h1 id="text1">Welcome to<br></h1>
<h2 id="text2">Linguini Party!</h2>
</div>
</body>
</html>
One strategy for accomplishing this is to create an html template along the lines of this...
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body id="Imagebg" >
<div id="container">
<h1 id="text1">$$TEXT1$$<br></h1>
<h2 id="text2">$$TEXT2$$</h2>
<img src="$$IMAGELOCATION$$"/>
</div>
</body>
</html>
This template has been instrumented with markers such as $$TEXT1$$. These will be replaced with customized text later.
Include the template as a resource, or as an external file, or wherever. I opt for including it as an embedded resource. Here's the settings...
You don't HAVE to use an embedded resource, you can use the WebBrowser to get the html also. I like using a resource because it avoids exceptions caused by missing or corrupt files.
The next step is easy. Here's a working View Model...
public class ViewModel
{
public string Text1 { get; set; }
public string Text2 { get; set; }
public string ImagePath { get; set; }
public string DestinationName { get; set; }
public void Start()
{
var resourceName = Assembly.GetExecutingAssembly().GetManifestResourceNames().Where(q => q.Contains("Template.html")).FirstOrDefault();
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
using (StreamReader reader = new StreamReader(stream))
{
string html = reader.ReadToEnd().Replace("$$TEXT1$$", Text1).Replace("$$TEXT2$$", Text2).Replace("$$IMAGELOCATION$$", ImagePath);
File.WriteAllText(DestinationName, html);
}
}
}
}
The View Model gets the various Text1 (etc) properties set by the caller, and then loads the HTML template and replaces the markers with custom content. Then it uses the static method on File to save it.
You can modify this strategy to use any other type of instrumentation as long as it's consistent. For a more scalable, full-blown solution, I suggest HtmlAgility. I have been using it for years.

How to disable the buttons of other URL opening using Iframe?

I m using iframe to open another webservice. there user can view the complete the nav of the targeted link. but i wan't to prevent the user to view the complete nav.
There are five items in the targetd URL like this:
Overview
Call Log
Terrif
Payment
Logout
<iframe id="subframe" frameborder="0" scrolling="no" src="login.aspx" style="float: left;height: 754px; margin-left: 118px; width: 727px;" ></iframe>
Now what i want is that, allow user only to view the Call Log.
How could be this possible to do?
Which steps could be taken to perform these all?
If the service is on your own domain, you can access the frames DOM like so:
var myFrame = frames["myFrame"]
var cssLink = document.createElement("link")
cssLink.href = "iframeStyles.css"; /* change this to the url for a stylesheet targetting the iframe */
cssLink .rel = "stylesheet";
cssLink .type = "text/css";
frames['myFrame'].document.body.appendChild(cssLink);
Also see this question:
How to add CSS class and control elements inside of the Iframe using javaScript.?
If the iframe loads a page from another domain, you may not alter it, because that would be against the same origin policy.
I used this a couple of months before.. Some edits might be required:
<div id="IframeWrapper">
<div id="iframeBlocker">
</div>
<iframe id="mainframe" src="http://www.xyz.com/"></iframe>
</div>
CSS:-
#IframeWrapper
{
position: relative;
}
#iframeBlocker
{
position: absolute;
top: 0;
left: 0;
width: 700px;
height: 450px;
}
#mainframe
{
overflow: hidden;
border-width: 0px;
}
OTHER ALTERNATE AND A BETTER ONE

Categories