I want to set the Title of Web page which is returning the PDF file stream as:
public ActionResult PrintInvoice(long ID)
{
var data = db.Documents.Where(x => x.InvoiceNumber == ID);
ReportDocument rd = new ReportDocument();
rd.Load(Server.MapPath("~/Reports/InvoiceDocument.rpt"));
Stream stream = rd.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);
stream.Seek(0, SeekOrigin.Begin);
return new FileStreamResult(stream, "application/pdf"); //For Showing PDF in Browser itself
}
and on this Page I want to set the Title.
How can I set the Title on this Page.
Currently the Title on the Page looks like as shown below in Image::
Have a look at HTTP Headers, like in that thread.
Try something like :
Response.AppendHeader("Content-Disposition", "inline; filename=your page title");
Also have a look at this thread which recommend :
return File(stream, "application/pdf", "your page title");
Keep in mind that this kind of data can be executed differently from different browsers.
This is what I ended up doing in my situation.
The controller code below consists of two actions. The first action returns a model I can use for setting the page title (this could just be a string depending on your use case). The second action is for getting the file contents. In my case I was storing the file contents in a database so I use an id to fetch the document.
The second action also sets the response headers so that the file name shows up properly when they try to download the file.
public IActionResult PreviewDocument(int id)
{
Document document = _legislationFolderService.GetDocument(id);
if (document == null)
return NotFound($"Could not find document with id of {id}");
return View(document);
}
public IActionResult PreviewDocumentContents(int id)
{
DocumentContents documentContents = _legislationFolderService.GetDocumentContents(id);
if (documentContents == null)
return NotFound($"Could not find contents for document with id of {id}");
Response.Headers.Add("Content-Disposition", $"inline; filename={documentContents.Document.Name}.pdf");
return new FileStreamResult(new MemoryStream(documentContents.Contents), "application/pdf");
}
In the view below (PreviewDocument.cshtml) I used an iframe to fill the page and link to the PreviewDocumentContents action. I didn't want the layout included from my main template so I set that to null and put up a basic html structure for the page, where I set the title right in the html.
#model EFloorFiles.Service.Models.Document
#{
Layout = null;
ViewBag.Title = Model.Name;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>#ViewData["Title"] - E-Floor Files</title>
<style type="text/css">
body, html {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
}
iframe {
width: 100%;
height: 100%;
border: none;
}
</style>
</head>
<body>
<iframe src="#Url.Action("PreviewDocumentContents", new { id = Model.Id })"></iframe>
</body>
</html>
Related
I'm trying to show the current logged in user in navbar "Name , profile photo and phone number".
in Home controller i used this to get the details
public async Task<IActionResult> Profile()
{
try
{
var me = await _graphServiceClient.Me.Request().GetAsync();
ViewData["Me"] = me;
// Get user photo
using (var photoStream = await
_graphServiceClient.Me.Photo.Content.Request().GetAsync())
{
byte[] photoByte = ((MemoryStream)photoStream).ToArray();
ViewData["Photo"] = Convert.ToBase64String(photoByte);
}
}
catch (System.Exception)
{
ViewData["Photo"] = null;
}
return View();
}
Then pass the data to _loginPartial by ViewData, but when i navigate to another page the details on _loginPartial navbar disappear and only show when i call the home controller again
#var user = ViewData["me"] as Microsoft.Graph.User;
#if (User.Identity?.IsAuthenticated == true)
{
<li class="nav-item">
#if(user != null){
<span class="navbar-text text"> Hello #user.DisplayName!</span>
<span class="navbar-text text"> #user.BusinessPhones.FirstOrDefault()</span>
}
</li>
if (ViewData["photo"] != null)
{
<img style="margin: 5px 0; width: 50px; border-radius:50%;"
src="data:image/jpeg;base64, #ViewData["photo"]" />
}
else
{
<img style="margin: 5px 0; width: 50px; border-radius:50%;"
src="~/img/defaultprofileicon.jpg" />
}
Is there any way to get user details on Program.cs as i use .net core mvc 6 and share this details across the app so they will appear in navbar in every page, Thank for help
but when i navigate to another page the details on _loginPartial
navbar disappear
Below is a demo to use session to pass the string to appear in navbar in every page , you can refer to it.
1.Register IHttpContextAccessor and session in Program.cs
builder.Services.AddSession();
builder.Services.AddHttpContextAccessor();
...
app.UseSession();
2.In the controller, set a session variable:
HttpContext.Session.SetString("Photo", "p1");
3.2.In _loginPartial.cshtml, inject IHttpContextAccessor implementation and use it to get the HttpContext and Session object from that.
#using Microsoft.AspNetCore.Http
#inject IHttpContextAccessor HttpContextAccessor
...
#HttpContextAccessor.HttpContext.Session.GetString("Photo")
result:
Using HttpClient, I make a GET request which returns a html response.
Request to url in method handler:
var response = string.Empty;
var result = await _httpClient.CreateClient().GetAsync(newUrl);
if (result.IsSuccessStatusCode)
{
response = await result.Content.ReadAsStringAsync();
var bytesResponse = Encoding.ASCII.GetBytes(response)
// How to open bytesResponse in a new browser tab?
}
Html response content from request:
<!DOCTYPE html>
<html lang="en">
<head>
<style>
</style>
</head>
<body>
<!-- body content -->
<script>
</script>
</body>
</html>
Attempting to add await Response.Body.WriteAsync(bytesResponse, 0, bytesResponse.Length); will throw an System.ObjectDisposedException: IFeatureCollection has been disposed. exception
Would appreciate assistance on how to display the response in a new browser tab.
Firstly,if you want to open a new browser tag,it cannot be done in razor handler.It need to be done in view.You need to decorate your link with the "_blank" attribute like this:
<a asp-page-handler="xxxxx" target="_blank">link</a>
Here is a demo worked:
test.cshtml:
<a asp-page-handler="Html" target="_blank">link</a>
test.cshtml.cs:
public IActionResult OnGet()
{
return Page();
}
public ActionResult OnGetHtml()
{
return base.Content("<div>Hello</div>", "text/html");
}
result:
In my application I have a folder structure where you can upload all kinds of files (jpg, png, pdf, txt etc.) You can download them directly as a file or you can view the file in the browser.
To display the file in the browser, I use the folowing controller action:
public virtual ActionResult FileDisplay(int fileId, bool isFile)
{
var viewmodel = _presenter.GetDocumentDisplayViewModel(fileId, isFile);
return base.File(viewmodel.Data, viewmodel.MediaType);
}
The file is displayed in the browser like this:
https://i.stack.imgur.com/TXmTy.jpg
The browser tab shows my controller name "FileDisplay" and (for this example) the dimensions of the image.
Question:
How can I display the filename in the brower tab title in stead of the controller name? This for all file types.
1. Content-Dispostion header
I have found several posts where they say to add the Content-Disposition header to the response with the filename:
Returning a file to View/Download in ASP.NET MVC
Make a file open in browser instead of downloading it
But this doesn't work.
2. Add filename to the File constructor
return base.File(viewmodel.Data, viewmodel.MediaType, viewmodel.FileName);
If I do this, the file is downloaded in stead of displayed in the browser.
3. PDF file title
I have found out that sometimes the browser tab title is correct! If I display a PDF file in the browser that has a file title (title in pdf properties, not the file name) the browser title is correct:
https://i.stack.imgur.com/orAZS.jpg
Can someone help me with this?
Workaround for now:
I have created a new action and view with a fullscreen iframe so I can set the title of this container view. The IFrame source is calling my File directly.
public virtual ActionResult FileDisplay(string fileName, int fileId, bool isFile)
{
var viewModel = new IFrameDocumentDisplayViewModel
{
FileName = fileName,
FileId = fileId,
IsFile = isFile
};
return PartialView("IFrameFileDisplayView", viewModel);
}
public virtual ActionResult GetFile(int fileId, bool isFile)
{
var viewmodel = _presenter.GetDocumentDisplayViewModel(fileId, isFile);
return base.File(viewmodel.Data, viewmodel.MediaType);
}
#model OnView.Models.ViewModels.Document.IFrameDocumentDisplayViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>#Model.FileName</title>
</head>
<body>
<iframe style="border: 0; position:absolute; top:0; left:0; right:0; bottom:0; width:100%; height:100%" src="#Html.Raw(Url.Action("GetFile", "Document", new { fileId = Model.FileId, isFile = Model.IsFile}))"></iframe>
</body>
</html>
So for now I can set the page title. But I am still curious how I can accomplish it without IFrame.
What the browser display as the tab title is the last part of the URL (the browser has no idea what is your controller name), so you could reformat your url like this :
localhost/OnView.Web/Document/FileDisplay/1685/True/MyTabName
Then the tab title would be MyTabName.
But changing a whole URL schema for such purpose also seems like a workaround...
Sidenote : I have the same problem, but my url is like this : FileDisplay/3?isFile=true and my tab title is 3 (in chrome. For IE, the tab title is the domain).
Try This:-
public virtual ActionResult FileDisplay(int fileId, bool isFile)
{
var viewmodel = _presenter.GetDocumentDisplayViewModel(fileId, isFile);
ViewBag.Title= viewmodel.FileName;
return base.File(viewmodel.Data, viewmodel.MediaType);
}
First of all I should say I have followed almost all the Questions and forum Post below
Stackoverflow Question 1
Stackoverflow Question 2
Stackoverflow Question 3
Stackoverflow Question 4
aspsnippets.com
Server Error in Application ... A potentially dangerous Request.Form value was detected
Avoiding the ‘A potentially dangerous Request.Form value was detected’
c-sharpcorner.com
A potentially dangerous Request.Form value was detected from the client in asp.net
all the thread mentioned to add <httpRuntime requestValidationMode = "2.0" /> or <pages validateRequest ="false" /> inside the web.config file , but this isn't working for me .
Once I did that and start debugging , getting this kind of error
Actually I'm trying to is Loading a HTML file into Rich Text Editor content then Once I click Save as PDF button saving that Rich Text Editor content to PDF file
these are the relevant controller class methods
[ValidateInput(false)]
public ActionResult output_xhtml()
{
PrepairEditor(delegate(Editor editor)
{
editor.LoadHtml("~/example.html");
});
return View();
}
[HttpPost]
[ValidateInput(false)]
public ActionResult output_xhtml(string m)
{
Editor theeditor = PrepairEditor(delegate(Editor editor)
{
});
theeditor.SavePDF("~/aaa.pdf");
return View();
}
PrepairEditor() method
protected Editor PrepairEditor(Action<Editor> oninit)
{
Editor editor = new Editor(System.Web.HttpContext.Current, "editor");
editor.ClientFolder = "/richtexteditor/";
editor.ContentCss = "/Content/example.css";
//editor.ClientFolder = "/Content/richtexteditor/";
//editor.ClientFolder = "/Scripts/richtexteditor/";
editor.Text = "Type here";
editor.AjaxPostbackUrl = Url.Action("EditorAjaxHandler");
if (oninit != null) oninit(editor);
//try to handle the upload/ajax requests
bool isajax = editor.MvcInit();
if (isajax)
return editor;
//load the form data if any
if (this.Request.HttpMethod == "POST")
{
string formdata = this.Request.Form[editor.Name];
if (formdata != null)
editor.LoadFormData(formdata);
}
//render the editor to ViewBag.Editor
ViewBag.Editor = editor.MvcGetString();
return editor;
}
//this action is specified by editor.AjaxPostbackUrl = Url.Action("EditorAjaxHandler");
//it will handle the editor dialogs Upload/Ajax requests
[ValidateInput(false)]
public ActionResult EditorAjaxHandler()
{
PrepairEditor(delegate(Editor editor)
{
});
return new EmptyResult();
}
this is screenshot of error occurring place in PrepairEditor() method
output_xhtml.cshtml view file
<!DOCTYPE html>
<html>
<head>
<title>RichTextEditor - Output XHTML</title>
</head>
<body>
<script type="text/javascript">
var editor;
function RichTextEditor_OnLoad(editor) {
editor = editor;
var content = true;
if (!content) {
setTimeout(function () {
editor.SetText("<table>.....</table>");
}, 1000);
return;
}
}
</script>
<script type='text/javascript'>
function RichTextEditor_OnLoad(editor) {
editor.SetWidth(1150); //Sets the width.
editor.SetHeight(612); //Sets the height.
}
</script>
#using (Html.BeginForm())
{
<div>
#Html.Raw(ViewBag.Editor)
<br />
<button id="btn_sumbit" type="submit" class="btn btn-danger submit">Save as PDF</button>
</div>
<br />
<div>
<h3>
Result html:
</h3>
<div>
#ViewBag._content
</div>
</div>
}
</body>
</html>
Once I did that and start debugging , getting this kind of error
Look at the error you are getting. You already have a <httpRuntime /> section in your web.config. You can't have two of them. Instead of adding a new one, change the existing one.
It is because you are passing HTML
add: [AllowHtml] above your method
[AllowHtml] goes on the property in your model not the controller method. Its namespace is System.Web.MVC
Here is my JQGrid Code:
click: function (e) {
debugger;
var id = $(e.target).closest("tr.jqgrow").attr("id");
rowdata = jQuery("#EmpTable").getRowData(id);
Data = { Id: rowdata.Id, Name: rowdata.Name, Designation: rowdata.Designation };
var url = 'http://localhost:50428/Script/Edit/';
return $.post(url, Data);
}
here is my controller code where the data is collecting
[HttpPost]
public ActionResult Edit(FormCollection form)
{
gridmodel properties = new gridmodel();
properties.Id = Convert.ToInt32(form["id"]);
properties.Name = form["Name"];
properties.Designation = form["Designation"];
ViewBag.id = properties.Id;
ViewBag.name = properties.Name;
ViewBag.designation = properties.Designation;
return View();
}
Now here is my View code
the data that is passing from the controller to the view
#model MVC5_JQGrid.Models.gridmodel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Edit</title>
</head>
<body>
<div>
Id:#ViewBag.id
<br />
Name:#ViewBag.name
<br />
Designation:#ViewBag.designation
</div>
</body>
</html>
But i am unable to load this page but in network ---> Response body i can see that these values are assigned
Update
Hello Venkata thanks for the answer i will keep the points which you mentioned and +1 from my side for the observation ,coming to the problem. it was resolved from oleg suggestion:(Here is the answer given by Oleg) The reason of your problem is the usage of $.post(url, Data); which just send data with respect of $.ajax({url: "/Script/Edit", data: Data, type: "POST"});. You need to do $.submit instead. If you would use HTTP GET then you can just assign new URL which includes parameters to location.href (something like location.href = "/Script/Edit?" + $.param(Data)). In case of HTTP POST one need to build with elements which contains (or just have on the page hidden form with all required elements with required name attributes) and use $.submit.
Thanks for the help from oleg and Venkata
Few Changes required in your code:
Observation and Notes:
Before fixing, we should know few points here regarding architecture, control-flow and standards
jQuery AJAX requests get response to its success callback handler(in your code you've missed success call)
In success function We should build or append or set HTML to target placeholder tag in existing page (let us say you have div for Edit section like <div id='editSection'>...</div> in your jqGrid page. you should bind the responseView to editSection div)
When we send AJAX request: In Controller.Action Instead of return View(); we should have return PartialView();
In your view.cshtml give preference to bind elements with Model rather than ViewData. You can get model to view if you do return PartialView(model); in the Action.
Try to reduce usage of ViewData or ViewBag in view.cshtml. Also business logic not recommended in Views.
Try to Follow best practices: Capitalization Conventions (in your code change gridmodel class name to GridModel)
By default routing url template will have {controller}/{action} (from your url Script is controller and Edit is action)
Make sure that you're passing correct Controller and Action names (Is Edit action located in the Controller with name ScriptController?)
Changes in JavaScript JQGrid Code:
url = '/Script/Edit/';
return $.post(url, Data).success(function(response){
//response datatype can be JSON or XML or HTML or text (In your case HTML Edit.cshtml View)
//update you target html tag with response view.
$('#editSection').html(responseView);
});
Changes in Controller:
[HttpPost]
public ActionResult Edit(FormCollection form)
{
var properties = new gridmodel();
properties.Id = Convert.ToInt32(form["id"]);
properties.Name = form["Name"];
properties.Designation = form["Designation"];
ViewBag.id = properties.Id;
ViewBag.name = properties.Name;
ViewBag.designation = properties.Designation;
return PartialView();
}
You can change above Edit Action like below if action require input parameters only id, name & designation
[HttpPost]
public ActionResult Edit(int id, string name, string designation)
{
var gridModel = new GridModel();
gridModel.Id = id;
gridModel.Name = name;
gridModel.Designation = designation;
ViewBag.id = gridModel.Id;
ViewBag.name = gridModel.Name;
ViewBag.designation = gridModel.Designation;
return PartialView(gridModel);
}
Hello Venkata thanks for the answer i will keep the points which you mentioned and +1 from my side for the observation ,coming to the problem. it was resolved from oleg suggestion:(Here is the answer given by Oleg) The reason of your problem is the usage of $.post(url, Data); which just send data with respect of $.ajax({url: "/Script/Edit", data: Data, type: "POST"});. You need to do $.submit instead. If you would use HTTP GET then you can just assign new URL which includes parameters to location.href (something like location.href = "/Script/Edit?" + $.param(Data)). In case of HTTP POST one need to build with elements which contains (or just have on the page hidden form with all required elements with required name attributes) and use $.submit. Thanks for the help from oleg and Venkata