Working with Kentico 11.0.26 CMS and a MVC website.
Have a custom content-only page type with an image field. After the image is uploaded on a page I need to display it on MVC site. But Kentico's generated code MyPageTypeProvider.GetMyPageType((int nodeId, string cultureName, string siteName) returns a page object that only contains the GUID of the image. No bytes, no URL.
How do I get the bytes or the URL of the uploaded image?
If you need the bytes, you can do this:
var attachment =DocumentHelper.GetAttachment(guid, SiteContext.CurrentSiteName, true);
var bytes = attachment.AttachmentBinary;
If you want a URL to the image, you can do something like this:
imageUrl = $"/getattachment/{guid}/attachment.aspx"
This documentation explains more ways to work with attachments.
You will need to either resolve the URL, or get file by GUID. Problem is, that Kentico Nuget API does not seem to provide enough options to get file binaries.
HelperMethods from Kentico.Content.Web.MVC NuGet seem to be good start:
https://github.com/Kentico/Mvc/tree/master/src/Kentico.Content.Web.Mvc
With these you can get file URL and use:
using (var client = new WebClient())
{
client.DownloadFile("http://example.com/file/song/a.mpeg", "a.mpeg");
}
Or you can write your own class or service, reference Kentico DLLs and use:
AttachmentBinaryHelper.GetFilePhysicalPath(string siteName, string guid, string extension)
Related
On my website each page has links that are created in the codebehind, where the links are the current URL with one query parameter changed. To do this, I've been using this method (this specific example is for the pagination):
var queryValues = HttpUtility.ParseQueryString(HttpContext.Current.Request.QueryString.ToString());
queryValues.Set("page", num);
string url = HttpContext.Current.Request.Url.AbsolutePath;
string updatedQueryString = "?" + queryValues.ToString();
string newUrl = url + updatedQueryString;
return newUrl;
This worked on my local version fine. However, when I created each page in Ektron and added a manual alias, the URLs generated still went to the file location in the solution. For example, my original page was /WebAssets/Templates/EventListView.aspx. I created the page in Ektron as /Alumni/Events/List. I can go to /Alumni/Events/List, but then when I click on a page button the page that loads is /WebAssets/Templates/EventListView.aspx?page=2 instead of /Alumni/Events/List/?page=2
I found one solution:
var rawUrl = HttpContext.Current.Request.RawUrl;
var url = rawUrl.Split('?')[0];
string newUrl = url + updatedQueryString;
Use the QuickLink property of the primary contentblock for /Alumni/Events/List, this will be the alias use want to use for your page links or for redirects to the same page. This is probably ContentData.QuickLink if you're already loading the ContentData at some point in the code.
Notes:
Aliasing may remove your "page" querystring parameter by default, to resolve this issue, edit your alias in the Workarea to have a "Query String Action" of "Append".
Make sure you preprend a "/" to the QuickLink value (if it's not absolute and not prepended already) if using it on the frontend, otherwise your links will bring you to something like /Alumni/Events/List/Alumni/Events/List?page=2, which is no good.
I have a view (with one or more images) that I also want to use as the body of an email message. The Model serving the view uses Url.Content() to retrieve the absolute image path. This approach works fine for web pages, but when I render the exact same view as the body of the email, then the image can not be found which is suggested by the incomplete path from the rendered html.
<img src="/Media/fe882a1d-3b77-4264-ab91-cade985ecbed.JPG"/>
I know that this problem can be fixed if I could access the full url such as with Url.Action with the
Request.Url.Scheme
overload for protocol. Is there a way to determine the fully qualified URL from Url.Content?
Try writting your own url extension method and resolve with the help of Uri.GetLeftPart & UriPartial.Authority
public static class UrlExtensions
{
public static string AbsoluteContent(this UrlHelper urlHelper
, string contentPath)
{
Uri requestUrl = urlHelper.RequestContext.HttpContext.Request.Url;
string absolutePath = string.Format("{0}{1}",
requestUrl.GetLeftPart(UriPartial.Authority),
urlHelper.Content(contentPath));
return absolutePath;
}
}
Then use Url.AbsoluteContent("~/media/image.jpeg") in your pages. It will render http://domain/media/image.jpeg
I'm trying to do pdf viewer functionality in mvc application. When user click the "read the pdf" link it should open a new tab/window and user should be able view the pdf file. So I checked the examples but I couldn't find. Could you suggest me any article or example ?
Show an anchor tag in your first view and pass an id (to identify what PDF to show)
#Html.ActionLink("read the pdf","view","doc",new { #id=123},null)
Now in the doc controller, have an action method which have a parameter called id and return the pdf there using the File method.
public ActionResult View(int id)
{
byte[] byteArrayOfFile=GetFieInByteArrayFormatFromId(id);
return File(byteArrayOfFile,"application/pdf");
}
Assuming GetFileInByteArrayFormatFromId is the method which returns the byte array format of the PDF file.
You can also return the PDF if you know the full path to the PDF file physically stored, using this overload.
public ActionResult Show()
{
string path="FullPAthTosomePDFfile.pdf";
return File(path, "application/pdf","someFriendlyName.pdf");
}
Show the PDF in a browser without downloading it
Based on the browser setting of the end user, the above solution will either ask user whether he/she wishes to download or open the file or simply download/open the file. If you prefer to show the file content directly in the browser without it gets downloaded to the user's computer, you may send a filestream to the browser.
public ActionResult Show(int id)
{
// to do : Using the id passed in,build the path to your pdf file
var pathToTheFile=Server.MapPath("~/Content/Downloads/sampleFile.pdf");
var fileStream = new FileStream(pathToTheFile,
FileMode.Open,
FileAccess.Read
);
return new FileStreamResult(fileStream, "application/pdf");
}
The above code expects you to have a pdf file named sampleFile.pdf in ~/Content/Downloads/ location. If you store the file(s) with a different name/naming convention, you may update the code to build the unique file name/path from the Id passed in.
If you want to display the PDF Content in browser, you can use iTextShare dll.
Refer the link http://www.codeproject.com/Tips/387327/Convert-PDF-file-content-into-string-using-Csharp.
Reading PDF content with itextsharp dll in VB.NET or C#
Short version:
I have a third-party MVC Extension that returns the FileResult. I would like to be able to process the file before returning it to the client. How can I do that?
If you're interested in boring details, read below:
I'm using Devexpress XtraReports for reporting purposes. The problem is that it's PDF Export is terrible, but RTF one works great. I would like to create action&result filter that would trick DevExpress into generating rtf instead of pdf (done) and convert the rtf to pdf using some other third-party library. The only problem is that I need to obtain rtf file from FileResult and return my own FileResult with the converted content.
//EDIT:
The code right now looks as follows:
public virtual ActionResult ReportExport(TParameters parameters)
{
return DevExpress.Web.Mvc.ReportViewerExtension.ExportTo(this.GetReport(parameters));
}
You said you are using a third-party MVC extension that returns a FileResult and you want to access the file details that are wrapped inside the result.
If you see the FileResult, it is an abstract class and I just know there are three built-in implementations are available in MVC (I don't aware about others): FileContentResult, FileStreamResult and FilePathResult.
All these classes provide public properties to access the details of the file. For ex. the FileContentResult contains a public property called FileContents that returns the content of a file as a byte array.
The third-party extension can return any FileResult implementation of the built-in types or badly(if you can't access those type) their own types as well. You can check the returned FileResult instance's type and cast it accordingly to access the file details.
var fileResult = ... returned by the MVC extension
if(fileResult is FileContentResult)
{
var fileContentResult = fileResult as FileContentResult;
var fileContent = fileContentResult.FileContents;
// process the file
}
else if(fileResult is FileStreamResult)
{
var fileStreamResult = fileResult as FileStreamResult;
var fileStream = fileStreamResult .Stream;
//...
}
else if(fileResult is FilePathResult) // this result only contains the path
// of the file name
{
//...
}
If you want make the things reusable you can implement a custom file result that takes the FileResult returned by the extension in the constructor and override the WriteFile method.
The FileResult probably writes the file contents to the response stream. You can use a standard ASP.NET response stream using a filter. See this ancient article for details:
https://web.archive.org/web/20211029043851/https://www.4guysfromrolla.com/articles/120308-1.aspx
Alternatively you could create your own ActionResult that invokes the DevExpress FileResult using a custom HttpContext with a fake response stream, which is where you would do your conversion.
I have this ASP.NET MVC application that I now want to separate out the image links to a CDN.
At this moment, images typically have this markup code:
<%= Html.ActionLinkWithImage("/Content/Img/Image1.png" ...
This works fine in development using the local web server (Cassini), and also when published the prod server.
But now I want the production URL to something like:
http://cdn.com/Img/Image1.png
How do I get this to work in an easy way, so that it works seamlessly in dev and after published to prod?
You can create a URL extension method that will, depending on a value from the Web.config file (or something else), generate the debug URL or the live URL.
public static MvcHtmlString CDNImageLink(this UrlHelper url, string imageName)
{
string urlFormat;
if((bool)ConfigurationManager.AppSettings["Debug"])
urlFormat = "/Content/Img/{0}";
else
urlFormat = "http://cdn.com/Img/{0}";
return MvcHtmlString.Create(string.Format(urlFormat, imageName));
}
You can then use this extension method anywhere you need an image url (including Html extension methods):
public static MvcHtmlString ActionLinkWithImage(this HtmlHelper html, string imageName)
{
UrlHelper Url = new UrlHelper(html.ViewContext.RequestContext);
string imageUrl = Url.CDNImageLink(imageName);
// generate the rest of the ActionLink using the imageUrl
}
Make sure you have the using statement for the namespace where the Url extension method is located at the top of the file where you declared the HTML extension method, otherwise it will not recognize it.
You can also modify your host file to redirect your cdn domain to another IP address. I use this to redirect static.myresources.com to localhost all the time and it keeps your html pretty clean.