URL Rewriting and a load images on my pages - asp.net

I am developing a website in ASP.Net(Forms approach) and rewrite my URL manually in my global.asax file and Application_BeginRequest method
look at this code :
<div style="background-image: url(<%= ResolveUrl("~/Storage/Images/admin-bk.gif") %>);">
I use this way in my aspx file to address images or css files or js files
Problem is here :
I have a gridview(FlexiGrid) and I use Jquery Ajax and call a webmethod to populate the grid.and my web method return html code .In this html code i have some images.
If URL equals to :
http://localhost/Cpanel/BasicDefinitions/Regions
my images load right.But if URl equals to
http://localhost/Cpanel/BasicDefinitions/Regions/
my images do not load.
To solve this problem I need to use ResolveUrl again in my webmethod.But as I know it is impossible to use it in a webmethod.So is there anyone out there to help me handle this error?
This is my webmethod :
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Xml)]
public static string FetchRegionList(int page, int rp, string sortname, string sortorder, string query, string qtype)
{
XDocument xmlDoc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("rows",
new XElement("page", page.ToString()),
new XElement("total", RegionBLO.Load().Count.ToString()),
new XElement("row", new XAttribute("Id", row.Id.ToString()),
new XElement("cell", "<img id='imgEdit' lang='" + row.Id.ToString() + #"' style='cursor:pointer;border:0px;' src='"+ ("~/Storage/Images/FlexGrid/edit.png") + "' title='Edit' />
<img id='imgDelete' lang='" + row.Id.ToString() + "' style='cursor:pointer;border:0px;' src='"+ ("~/Storage/Images/FlexGrid/close.png") + "' title='Delete' />")
)
)
);
StringBuilder builder = new StringBuilder();
using (TextWriter writer = new StringWriter(builder))
{
xmlDoc.Save(writer);
}
return builder.ToString();
}
Thanks, Ali

Instead of adding the images as <img> tags, you could add <span> or <a> tags with predefined CSS classes edit and close.
new XElement("cell", "<a ... class='edit'></a><a ... class='delete'></a>")
Then you can use the following CSS to give those elements a background image:
a.edit, a.delete {
display: inline-block;
width: 16px;
height: 16px;
cursor: pointer;
border:0px;
background-repeat: no-repeat;
}
a.edit {
background-image: url(../Images/FlexGrid/edit.png);
}
a.delete {
background-image: url(../Images/FlexGrid/delete.png);
}
The paths to the images from the CSS file are always relative to the CSS file itself. So you don't have to worry about using ResolveUrl server-side, the browser will find the image regardless of the virtual path that the site is running from.
In this case the file locations are:
~/storage/images/edit.png
~/storage/images/delete.png
~/storage/stylesheets/site.css
And so you can see that the path ../Images/FlexGrid/edit.png, when used in the CSS file will point to the image.

Related

Iframe shows ActionMethod name while loading PDF file in ASP MVC

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?

Error in displaying image in HTML file

In my MVC2 application I use CKEditor where I allow the user to create a PDF document.
First the CKEditor content will get converted into HTML file and later as PDF document.
I have provided a button called Arrow on click of it image of an arrow should get inserted. In editor image gets displayed successfully but in HTML and PDF file image is not getting displayed inplace of it alt content gets displayed.
Code for an arrow button:
<input type="button" class="green_button" id="arrow" name="Arrow" value="Arrow" style="width: 110px; height: 30px; background-color: #FFFFFF;" onclick="return arrow_onclick()" />
function arrow_onclick() {
var editor = CKEDITOR.instances.message;
editor.insertHtml(' <input type="image" alt="arrow" src="../../PDFimages/arrow-left-up.jpg" style="height:100px; width:100px" />');
}
Controller code:
public ActionResult CreateFile(FormCollection data)
{
var filename = data["filename"];
var htmlContent = data["content"];
string sFilePath = Server.MapPath(_createdPDF + filename + ".html");
htmlContent = htmlContent.Trim();
if (!System.IO.File.Exists(sFilePath))
{
using (FileStream fs = new FileStream(sFilePath, FileMode.Create))
{
using (StreamWriter w = new StreamWriter(fs, Encoding.UTF8))
{
w.Write(htmlContent);
}
}
string filename1 = Path.GetFileNameWithoutExtension(sFilePath);
string name = Server.MapPath(_createdPDF + filename1 + ".pdf");
HTML2PDF.SetModulePath(#"C:\Documents and Settings\shubham\My Documents\visdatemplatemanger\visdatemplatemanger\bin");
using (PDFDoc doc = new PDFDoc())
{
if (HTML2PDF.Convert(doc, sFilePath))
doc.Save(name, pdftron.SDF.SDFDoc.SaveOptions.e_linearized);
}
System.IO.File.Delete(sFilePath);
UploadURL(name);
}
return View();
}
Before submit your form, you should set textarea value from CkEditor and make your action that accepts the post has this annotation applied [HttpPost, ValidateInput(false)]
$("#content").val(CKEDITOR.instances.message.getData());
And check your src value. Maybe should using:
src="#(Url.Content( "~/PDFimages/arrow-left-up.jpg" ))"
if PDFimages folder included in Project/Content

GetImageThumbnail() with dimensions

In our ASP.NET MVC 3 We are currently generating thumbnail images on the fly with the following code:
public void GetImageThumbnail(string imageName)
{
WebImage wbImage = new WebImage("~/assets/images/gallery/"+imageName+".jpg");
int width = 220;
wbImage.Resize(width, (int)((double)wbImage.Height * width / wbImage.Width));
wbImage.FileName = imageName+"_small.jpg";
wbImage.Write();
}
and displaying them in the view like this:
<img src="#Url.Action("GetImageThumbnail", new {imageName = "motherboard"})" alt="" />
How can we control the image size on the view and generate the complete <img> tag from scratch? We need to specify the image dimension and obtain an <img> tag the contains the width and height properties.
Thanks.
My first thought is to create your own HTML helper method which does all of the work. Something you would consume like:
#Html.ThumbnailImg("motherboard")
That method does the thumbnail work and can output the full desired markup. More info: http://www.asp.net/mvc/tutorials/older-versions/views/creating-custom-html-helpers-cs. For what it's worth, I prefer the extension method design. It seems more palatable to other devs.
UPDATE:
There is a little bit of chicken-and-egg that I didn't think about before. Perhaps something like:
public static MvcHtmlString ThumbnailImg(
this HtmlHelper html,
UrlHelper url,
String imageName,
String elementID,
String altText)
{
var img = new TagBuilder("img");
if (String.IsNullOrEmpty(elementID) == false) img.MergeAttribute("id", elementID);
if (String.IsNullOrEmpty(altText) == false) img.MergeAttribute("alt", altText);
// Generate and cache thumnail here, determining height and width
// ...
var src = url.Action("GetImageThumbnail", new { imageName = imageName });
img.MergeAttribute("height", height);
img.MergeAttribute("width", width);
img.MergeAttribute("src", src);
return MvcHtmlString.Create(img.ToString(TagRenderMode.SelfClosing));
}

Referring an image that is located on my C drive in asp.net MVC

I want to refer an image located in c:/image/ff.gif/. How can I do that? I tried to do it with img src, but couldn't make it to work. Any ideas?
The image needs to be part of the site if you want to use it directly. If it is situated outside of your site root you could write an action that will fetch the image and serve it:
public ActionResult MyImage()
{
return File(#"c:\imagefolder\imagell.gif", "image/gif");
}
And then use this action:
<img src="<%= Url.Action("myimage") %>" alt="image description" />
Check this here How I am using in MVC.
In View:
<img src="#Url.Action("FileDownload",new { name=i.fileName})" alt="#i.fileName"/>
In Controller:
public FileResult FileDownload(string name)
{
string FilePath= _ConfigPath+ "\\" + name;
return File(FilePath, "application/force-download", name);
}

ASP.NET MVC URL auto-resolution in CSS files

In normal WebForms scenario, any root-relative URLs (e.g. ~/folder/file.txt) inside CSS files such as:
.form { background-image: url(~/Content/Images/form_bg.gif); }
will automatically get resolved during runtime if I specify
<head runat="server">
In the referencing page.
However, that is no longer happening on an ASP.NET MVC Beta1 website.
Is there a way I could enable this functionality without resorting to hacks or CSS-loader file? Like maybe HttpModules or something?
Or am I not desigining my website correctly? What is supposed to be a good design?
Since original ASP.NET WebForms already has this feature, I'd prefer to utilize any existing functionality if possible. But I don't have much clue.
This web application will be deployed in several environments where the ~ root folder might not be obvious.
EDIT: I mean the url in the file's CONTENT not the file's url itself.
I would not bother with the auto-root-finding ~ character. I understand that you want the same solution to work where the root directory differs between deployments, but within the CSS document you shouldn't have any problems using relative paths. The paths in the CSS document (to the image URL in your example) will always be relative to the location of the CSS file regardless of the path of any page that loads that CSS file. So if your images are in ~/Content/Images and your stylesheets are in ~/Content/Stylesheets, you'll always be able to use background-image: url(../Images/form_bg.gif); and it will work regardless of the location of the page that loads the stylesheet.
Is there a reason this wouldn't work?
One trick I have used in the past, was to actually make my CSS file have a .ASPX extension, and set the ContentType property in the page signature:
<%# Page Language="C#" ContentType="text/css" %>
body {
margin: 0;
padding: 0;
background: #C32605 url(<%= ResolveUrl("~/Content/themes/base/images/BodyBackground.png") %>) repeat-x;
font-family: Verdana, Arial, sans-serif;
font-size: small;
color: #d7f9ff;
}
This will ensure that the CSS file goes through the ASP.NET framework, and replaces the server side code with your relative path.
Here are some resources on implementing IHttpModule to intercept web requests to your app...
Write/adapt one to check for filetype (e.g. pseudocode: if (request ends with ".css") ...)
then use a regular expression to replace all instances of "~/" with System.Web.VirtualPathUtility.ToAbsolute("~/")
I don't know what this will do to performance, running every request through this kind of a filter, but you can probably fiddle with your web.config file and/or your MVC URL routes to funnel all .css requests through this kind of a filter while skipping past it for other files.
Come to think of it, you can probably achieve the same effect inside an ASP.NET MVC app by pointing all your CSS refrences at a special controller.action that performs this kind of preprocessing for you. i doubt that would be as performant as an IHttpModule though.
If you're trying to parse the ~/ out of any file, including text files, javascript, etc, you can write a handler that assigns a filter to it and you can use that to search for those paths... for example...
public class StringParsingFilter : MemoryStream {
public Stream OriginalStream {
get { return this.m_OriginalStream; }
set { this.m_OriginalStream = value; }
}
private System.IO.Stream m_OriginalStream;
public StringParsingFilter() : base() {
this.m_OriginalStream = null;
}
public override void Flush() {
this.m_OriginalStream.Flush();
}
public override void Write(byte[] buffer, int offset, int count) {
//otherwise, parse for the correct content
string value = System.Text.Encoding.Default.GetString(buffer);
string contentType = HttpContext.Current.Response.ContentType;
//Do any parsing here
...
//write the new bytes to the stream
byte[] bytes = System.Text.Encoding.Default.GetBytes(value);
this.m_OriginalStream.Write(bytes, offset, count + (bytes.Length - buffer.Length));
}
}
And you'll write a custom handler to know when to assign this filter... like the following...
public class FilterControlModule : IHttpModule {
public void Init(HttpApplication context) {
HttpApplication oAppContext = context;
oAppContext.BeginRequest += new EventHandler(_HandleSettingFilter);
}
private void _HandleSettingFilter(object sender, EventArgs e) {
//You might check the file at this part to make sure
//it is a file type you want to parse
//if (!CurrentFile.isStyleSheet()) { return; }
...
//assign the new filter
StringParsingFilter filter = new StringParsingFilter();
filter.OriginalStream = HttpContext.Current.Response.Filter;
HttpContext.Current.Response.Filter = (Stream)filter;
}
}
It may have actually been easier just to say "look up IHttpModules" but this is some code that I've used to parse files for paths other than ASP.net files.
You'll also have to change some things in your IIS settings to allow the files to be parsed by setting the ASP.net ISAPI to be a wildcard for all of the files that get handled. You can see more at this website, if you're using IIS6 that is...
You can also use this to modify any file types so you could assign some filters for images, some for javascript or stylesheets or ... really anything...
You could use an URL Rewriter to fix the URL as the request comes in, though I am not so sure it is so much elegant as a hack in this case.
I created a PathHelper util class that gives me all the paths I need.
For example
<link href="<%=PathHelper.CssUrl("FormulaIndex.css")%>" rel="Stylesheet" type="text/css"/>
Gives me the correct full url with the help of System.Web.VirtualPathUtility.ToAbsolute() and my own convention (content/css/yourFile.css).
I did the same for js, xml, t9n, pics...
Its central, reusable and now I only had to change one line to catch the move of the scripts folder from content/js to Scripts in all my websites and pages.
A moronic move if you ask me, but it's reality in the current beta :(

Resources