I have an iframe which uses a Url.Action to open a PDF from an action controller. Is it possible to open this PDF on a certain page? Determined by a value in the model e.g. #Model.FilePage
iframe:
<iframe width="700" height="1600" src="#Url.Action("OpenPDF", new { id = 8 })"></iframe>
controller action:
public ActionResult OpenPDF(int? id)
{
CompletedCamp completedCamp = db.CompletedCamps.Find(id);
string filepath = Server.MapPath(Path.Combine("~/Surveys/" + completedCamp.SurveyName));
return File(filepath, "application/pdf");
}
To open on specific page, add #page=[page number] to the end of src
<iframe width="700" height="1600" src="#Url.Action("OpenPDF", new { id = 8 })#page=4"></iframe>
if page number should be from the model, do
public ActionResult Index()
{
MyViewModel m = new MyViewModel() { FilePage = 4 };
return View(m);
}
...
#model MVC.MyViewModel
<iframe width="700" height="1600" src="#Url.Action("OpenPDF", new { id = 8 })#page=#Model.FilePage"></iframe>
Related
I'm developing a method to display the photo of logged user in a layout page.
It looks like the method is fine, and returns for me the image path, but I don't know to make it works on <img src="">, or I can do it with some razor function?
If I call my method from url like http://localhost:29469/User/LoadPhoto, it returns the correct path.
The layout is not typed, so I can not display it like Model.Attribute
public ActionResult LoadPhoto()
{
if (User.Identity.IsAuthenticated)
{
var userStore = new UserStore<User>(new ERPIdentityDbContext());
var userManager = new UserManager<User>(userStore);
var xUser = userManager.FindById(User.Identity.GetUserId());
string xPhotoPath = HttpContext.Server.MapPath(#"~/Images/Users/") + xUser.FotoPath ;
return Content(xPhotoPath);
}
return View();
}
I want to use return for LoadPhoto method in <img src="">
If your photos are JPGs, return a File ActionResult with the image/jpeg content type:
string xPhotoPath = HttpContext.Server.MapPath(#"~/Images/Users/") + xUser.FotoPath ;
return File(xPhotoPath,"image/jpeg");
I have an action who displays a PDF in a new browser tab.
public ActionResult Print()
{
var cd = new ContentDisposition
{
FileName ="something.pdf",
Inline = true
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(reportResponse.Data.Document, MediaTypeNames.Application.Pdf);
}
The filename is working fine. When I download the file it has the name I want "something.pdf".
The problem is when google chrome opens the PDF in a new browser tab, it displays the controller action name (Print) as the title of the PDF. That's what I'm trying to change. I attached a picture for clarification.
View code:
Url.Action("Print", "Controller", new { area = "Area" }), new { #target = "_blank" }
To the action method pass parameter of the file name and make sure parameter name is 'id'.
View code:
Url.Action("Print", "Controller", new { id = "filename", area = "Area" }), new { #target = "_blank" }
Adding to kodandarami's answer,
When you're passing a PDF file back from ASP.NET MVC, the page title is set to the last url part of the route config used to get to your controller.
Knowing this, you can dynamically name the title by setting up a parameter as part of the route config for your controller eg:
routes.MapRoute(
"Print",
"print/{pdfName}",
new { controller = "Print", action = "Index", pdfName = UrlParameter.Optional }
);
Then MVC will use this value instead as it considers it a separate page.
Use it in the url as
"/print/this-is-my-pdf-title" not '/print?pdfName=this-is-my-pdf-title".
As a querystring parameter, MVC will just fall back to calling the PDF 'print'.
Note:
As mentioned in this related question,
IIS has more strict rules about forbidden characters when the text is before the query string '?' character. You are not allowed <,>,*,%,&,:,\ (See MS Reference)
Any of these characters, even when encoded will give you a 'Path is potentially dangerous' 400 error.
Make sure to remove/replace these forbidden characters.
.
I solved this problem by using a iframe.
Create an action which fills the title and pdf url.
public ActionResult ArticleSpecification(int ArticleID)
{
using (var context = new myEntities())
{
Article article = context.Article.FirstOrDefault(a => a.ArticleID == ArticleID);
ViewData["Title"] = article.Code + " - " + article.Description;
ViewData["PdfSource"] = "ArticleSpecificationPdf?ArticleID=" + article.ArticleID;
return View("~/Views/Specification/pdfview.cshtml");
}
}
pdfview.cshtml: with a iframe to view the pdf and title.
#{
Layout = "";
}
<!DOCTYPE html>
<html>
<head>
<title>#ViewData["Title"]</title>
<style>
html, body, iframe {
height: 100%;
width: 100%;
margin: 0;
border: 0;
}
body {
overflow-y: hidden;
}
</style>
</head>
<body>
<iframe src="#ViewData["PdfSource"]"></iframe>
</body>
</html>
The action to return the pdf content.
public FileResult ArticleSpecificationPdf(int ArticleID)
{
using (var context = new myEntities())
{
PdfFile file = null;
Article article = context.Article.FirstOrDefault(a => a.ArticleID == ArticleID);
if (article != null && article.SpecificationPdfID != null)
file = context.PdfFile.FirstOrDefault(a => a.PdfFileID == article.SpecificationPdfID);
return new FilePathResult(file.path, "application/pdf");
}
}
Try the following return statement:
return File(reportResponse.Data.Document, MediaTypeNames.Application.Pdf, "something.pdf");
I have changed a Get submit using:
<a style="text-decoration:none;" href="#Url.Action(item.ListAction, item.ListController, new { ids = string.Join("-", item.Ids), categoryId = item.Id, search = (string)ViewBag.Search, location = (string)ViewBag.Location })">
To:
#using(Html.BeginForm(null, null, FormMethod.Post, new { id = "homeCategoryForm" }))
{
#Html.AntiForgeryToken()
#Html.Hidden("ids")
#Html.Hidden("categoryId")
#Html.Hidden("search")
#Html.Hidden("location")
}
Submiting it with JQuery:
$(document).on("click", ".innerelement", function (e)
{
var elementId = e.target.id.split('_')[1];
action = "/" + $("#controller_" + elementId).val() + "/" + $("#action_" + elementId).val();
$("#homeCategoryForm").attr("action", action);
$("#ids").val($("#ids_" + elementId).val());
$("#categoryId").val($("#categoryId_" + elementId).val());
$("#search").val($("#search_" + elementId).val());
$("#location").val($("#location_" + elementId).val());
$("#homeCategoryForm").submit();
});
The controller:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public virtual ActionResult GetAllByIds(string ids, int categoryId, string search, string location)
{
AdGetAllByCategoryListViewModel model = new AdGetAllByCategoryListViewModel();
model.Ads = Mapper.Map<IList<AdGetAllByCategoryDto>, IList<AdGetAllByCategoryViewModel>>(_adService.GetAllByIds(ids));
model.Category = Mapper.Map<CategoryDto, CategoryViewModel>(_categoryService.GetById(categoryId));
return View(MVC.Ad.Views.GetAllByCategory, model);
}
The problem is that the View using the Form Post method is producing a application/json View (Source) and not the text/html.
EDIT:
The view is been rendering from a PartialView, so maybe it's the problem?
I have tested with PartialView and the HTML of the View is rendered but not the all Layout View.
Any idea why?
Thanks
I found the Problem:
In the Layout of the View I have a coment form:
<!-- Comments form container -->
<div class="comentsform">
<!-- Comments form -->
#{ Html.RenderAction(MVC.Comment.Create()); }
</div>
<!-- Comments form container closed -->
The Controller is:
public virtual PartialViewResult Create()
{
return PartialView();
}
The issue here is that I also have a JSON Action to send the comment by jQuery:
[HttpPost]
[ValidateAntiForgeryToken]
public virtual JsonResult Create(CommentViewModel commentViewModel)
{
CommentDto comentDto = Mapper.Map<CommentViewModel, CommentDto>(commentViewModel);
_commentService.Create(comentDto);
commentViewModel.Result = HeelpResources.CommentViewModelResultMsgOk;
return Json(commentViewModel);
}
So it seems that, when the Layout is rendered coming from a Form POST action, it will search for all the [HttpPost] Actions of the Html.RenderAction presents in the Layout.
In this case, and because I have a Html.RenderAction with an [HttpPost] Action of type JsonResult, the all result View is converted in a JSON response.
So now, the only thing I have to do is to change the name of the JSON Action to public virtual JsonResult CreateSend for example, and Problem Solved!
Thanks again for the availability of all to help.
I am trying to create a sample MVC4 webpage with partialViews
on my parent page ,eg., Index.cshtml page I am displaying a partialView page which will allow the user to view/update profile photo
When the index page loads ,I need this partial page to show up the photo if photo is available
once the page is loaded ,when the user uploads a new photo,I need only the partialView page to do an ajax postback and show up the new photo .
I am able to load the page with photo fetched from DB,
I am able to Save new photo to db by clicking "#btnPhotoUpload" button.
But after saving the photo ,the partialview is not getting refreshed automatically.Please help me how to get my partialview page to refesh and display the updated photo.
Here is my index page ie., "Index.cshtml"
#model MvcSamples.Models.ViewModels.UserInfoViewModel
#{
ViewBag.Title = "Ajax Partial Postback demo";
ViewBag.UserId = 1;
}
<h2>PersonalInfo example</h2>
<div id="photoForm">
#Html.Partial("_UserPhoto")
</div>
<div id="OtherDetails">
#Html.Partial("_UserDetails")
</div>
Here is my PartialView, i.e. _UserPhoto.cshtml
#model MvcSamples.Models.ViewModels.UserInfoViewModel
#using (Ajax.BeginForm("SaveProfilePhoto", "Example", new { id = "1" }, new AjaxOptions { UpdateTargetId = "photoForm", OnSuccess = "onSuccess" }, new { encType = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<a>
<img id="imgPhoto" width="100px" height="100px"/>
<label for="photo">Photo:</label>
<input type="file" name="photo" id="photo" />
<input id="btnPhotoUpload" type="button" value="Apply" />
</a>
<script type="text/javascript">
$(document).ready(function () {
$("#imgPhoto").attr('src', "#Url.Action("GetProfileImage", "Example", new { id = ViewBag.UserId })");
$("#btnPhotoUpload").click(function (event) {
//on-click code goes in here.
event.preventDefault();
SavePhotoToDb();
});
function SavePhotoToDb() {
var json;
var data;
$.ajax({
type: "POST",
url: "/Example/SaveProfilePhoto",
data: new FormData($("#form0").get(0)),
dataType: "html",
contentType: false,
processData: false,
success: saveItemCompleted(data),
error: saveItemFailed
});
}
function saveItemCompleted(data) {
$("#photoForm").html(data);
}
function saveItemFailed(request, status, error) {
}
});
</script>
}
Here is my controller ExampleController:
namespace MvcSamples.Controllers
{
public class ExampleController : Controller
{
IUserDetails usr = new UserDetails();
// GET: /Example/
[HttpGet]
public ActionResult Index()
{
//usr.GetProfilePhoto(WebSecurity.GetUserId(User.Identity.Name));
if (!string.IsNullOrWhiteSpace(User.Identity.Name))
{
ViewBag.UserId = WebSecurity.GetUserId(User.Identity.Name);
}
UserInfoViewModel model = new UserInfoViewModel();
model.GenderList = usr.FillGenderTypesDropDownList();
return View(model);
}
[HttpPost]
public ActionResult SaveProfilePhoto(HttpPostedFileBase photo, UserInfoViewModel model)
{
string path = #"C:\Temp\";
if (photo != null)
{
model.UserId = 1;//WebSecurity.GetUserId(User.Identity.Name);
ViewBag.UserId = model.UserId;
var binary = new byte[photo.ContentLength];
photo.InputStream.Read(binary, 0, photo.ContentLength);
UserPicModel upModel = new UserPicModel();
upModel.UserPhoto = binary;
upModel.UserId = model.UserId;
usr.InsertProfilePhoto(upModel);
}
return PartialView("_UserPhoto", model);
}
public FileResult GetProfileImage(int id)
{
byte[] barrImg = usr.GetProfilePhoto(id);
return File(barrImg, "image/png");
}
}
}
Update:
As #David Tansey suggested ,I added code to refresh image inside SaveCompleted(data).
function RefreshImage() {
$("#imgPhoto").attr('src', function () {
// the datetime portion appended to the url avoids caching issues
// and ensures that a fresh image will be loaded every time
var d = new Date();
return this.src + '?' + d.getTime();
});
}
But the above code is refreshing the image only after I click the upload button twice .
Actually I need this to refresh the image immediately after the $("#btnPhotoUpload").click. Any suggestions?
I also tried disabling cache at the controller but no luck:
[OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
I am pretty sure the problem is that the browser is caching the image file and does not 'perceive' the need to bring it across the wire again after you upload a new one.
Look at the following post for a description of how to attach a dummy (yet dynamic) query string value to prevent the caching from occuring. I think this approach will solve your problem.
asp.net mvc jquery filling image
Hope that helps.
I have a View that displays a list of images and i am now trying to get it to display the images as thumbnails. Well, i'm pretty sure i got most of it right using VirtualPath's from a custom ActionResult although i can't seem to figure out what it is making the VirtualPath url?? BTW, i'm using XML to store the data from the images instead of SQL. Here is my code:
Code from my custom ActionResult:
public class ThumbnailResult : ActionResult
{
public ThumbnailResult(string virtualPath)
{
this.VirtualPath = virtualPath;
}
public string VirtualPath { get; set; }
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.ContentType = "image/bmp";
string fullFileName =
context.HttpContext.Server.MapPath("~/Galleries/WhereConfusionMeetsConcrete/" + VirtualPath);
using (System.Drawing.Image photoImg =
System.Drawing.Image.FromFile(fullFileName))
{
using (System.Drawing.Image thumbPhoto =
photoImg.GetThumbnailImage(100, 100, null, new System.IntPtr()))
{
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
thumbPhoto.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
context.HttpContext.Response.BinaryWrite(ms.ToArray());
context.HttpContext.Response.End();
}
}
}
}
}
Code for my Controller:
public ActionResult Thumbnail(string id)
{
return new ThumbnailResult(id);
}
Code for my View:
<% foreach (var image in ViewData.Model) { %>
<img src="../Galleries/TestGallery1/thumbnail/<%= image.Path %>" alt="<%= image.Caption %>" />
<br /><br /><%= image.Caption %><br /><br /><br />
<% } %>
Any help would be greatly appreciated!! Let me know of any questions you have as well. :) Thanks!
From what I can see you are using the VirtualPath string member in the ThumbnailResult custom action to identify the last portion of the image url. So for example if your site is located at c:\wwwroot\Galleries\WhereConfusionMeetsConcrete and the image files are located inside this folder like image1.bmp, image2.bmp, ... you could only pass the image filename to the custom action result constructor which is called in the controller action and passed the id parameter. So in order to show a thumbnail for image1.bmp in your view you could do this:
<img src="<%= Url.RouteUrl(new { controller = "home", action = "Thumbnail", id = "image1.bmp" }) %>" alt="" />
Of course this assumes that you have a default route like this:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);