how to show image not found in Asp.net MVC - c#

I have a asp.net mvc project. in a speicific views i call the four image from different different folder inside my proect.
sometime image can not be found. i want to set a image for every folder because all 4 folder contain different diffent size of image so i need to set the image of specific size for each folder.
how i can show the default image when the image not found any way to do that.i means call the none.png when the directory not have image who i called in the views.
are their any way to show the image in the case of image not found.
any way to do that in asp.net 4 MVC 3. using web.config or setting anything else.

Easiest way to do this is with a html helper. Please be mindful of the extra performace hit of checking the file system before even showing an image filename. The hit is a small one though, so you won't notice any issues unless you are getting very high traffic. Then you can implement some sort of caching so the app "knows" if the file exists or not.
You can use a custom html helper for it
public static class ImageHtmlHelpers
{
public static string ImageUrlFor(this HtmlHelper helper, string contentUrl)
{
// Put some caching logic here if you want it to perform better
UrlHelper urlHelper = new UrlHelper(helper.ViewContext.RequestContext);
if (!File.Exists(helper.ViewContext.HttpContext.Server.MapPath(contentUrl)))
{
return urlHelper.Content("~/content/images/none.png");
}
else
{
return urlHelper.Content(contentUrl);
}
}
}
Then in your view you can just make the url using:
<img src="<% Html.ImageUrlFor("~/content/images/myfolder/myimage.jpg"); %>" />
EDIT: As Jim pointed out, I haven't really addressed the sizing issue. Personally I use automatic size request management/size which is a whole other story, but if you are concerned about the folders/sizes simply pass that information in to build the path. As below:
public static class ImageHtmlHelpers
{
public static string ImageUrlFor(this HtmlHelper helper, string imageFilename, ImageSizeFolderEnum imageSizeFolder)
{
UrlHelper urlHelper = new UrlHelper(helper.ViewContext.RequestContext);
string contentUrl = String.Format("~/content/userimages/{0}/{1}", imageSizeFolder, imageFilename);
if (!File.Exists(helper.ViewContext.HttpContext.Server.MapPath(contentUrl)))
{
return urlHelper.Content(String.Format("~/content/userimages/{0}/none.png", imageSizeFolder));
}
else
{
return urlHelper.Content(contentUrl);
}
}
}
Then in your view you can just make the url using:
<img src="<% Html.ImageUrlFor("myimage.jpg", ImageSizeFolderEnum.Small); %>" />
Have suggested an Enum for better programmatic control if the folder is a fixed set, but for a quick and nasty approach, not reason why you can't just use a string if the folder is db generated etc.

Don't know all that much MVC, but here is my idea nonetheless:
Have a specific controller which fetches an image based on whatever your logic. Like Michael said have something (image) returned on a successful audit - meaning if image is found. If not found return a status code 404 or something like that.
Handle the rest via javascript on the client. So in the img tag write something for the onerror event. May be replace the img source w/ your image not found poster image file. Here somewhat (but not exactly) how to do that via jquery.
$(function(){
$('#myimg').error(function(){
$('#result').html("image not found");
});
});
PS: http://jsfiddle.net/Fy9SL/2/ if u are interested in the full demo of jquery code.

public static MvcHtmlString Image(this HtmlHelper helper, string src, string alt)
{
var builder = new TagBuilder("img");
// Put some caching logic here if you want it to perform better
UrlHelper urlHelper = new UrlHelper(helper.ViewContext.RequestContext);
if (!File.Exists(helper.ViewContext.HttpContext.Server.MapPath(src)))
{
src = urlHelper.Content("~/content/images/none.png");
}
else
{
src = urlHelper.Content(src);
}
builder.MergeAttribute("src", src);
builder.MergeAttribute("alt", alt);
return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing));
}

You can make a controller action return a FileResult, and accept a parameter of type string which describes the image path.
The controller action tries to load the image from disk and return it as a FileResult, or if the file is missing from the disk, return a place holder 'image not found' image instead.
Then to display the image (or its placeholder) you would set the src attribute of your img element to the controller action rather than the image directly.

Related

Can I save only one DomElement to jpg use DotNetBrowser?

in Documentations, I find How to save the full page - link to article
but for me need save only one element from page to jpg
It's really?
How can I do it with DotNetBrowser?
DotNetBrowser does not provide an API which allows saving the specific DomElement as a JPG.
However, if you need to save resources (such as images, favicons, etc.) from the webpage, take a look at the Browser.Context.NetworkService.ResourceHandler interface. Here is a code snippet:
class SampleResourceHandler : ResourceHandler
{
public bool CanLoadResource(ResourceParams parameters)
{
if (parameters.ResourceType == ResourceType.IMAGE)
{
Console.WriteLine("image URL: " + parameters.URL);
}
return true;
}
}
This article contains more information about how to handle resources loading

ASP.NET WebApi - reference file on server securely

Alright, so I would like to create a thumbnail storage with a couple of png image files in it.
I created a directory on the server side. Now in my controller I would like to process requests for images.
Currently the code of my controller looks like this:
public class ThumbnailController : ApiController
{
[Route("api/v1/thumbnail")]
[HttpGet]
public HttpResponseMessage GetThumbnail(string id)
{
var result = new HttpResponseMessage(HttpStatusCode.OK);
string filePath = $#"D:\server_data\Images\Thumbnails\{id}.png";
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Invalid file");
var image = Image.FromFile(filePath);
using (var memoryStream = new MemoryStream())
{
image.Save(memoryStream, ImageFormat.Jpeg);
result.Content = new ByteArrayContent(memoryStream.ToArray());
}
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
return result;
}
}
Now this one has a security issue: if I call something like http://my.address.com/api/v1/thumbnail?id=../securefile.png I would essentially get the securefile.png image file located in the parent directory. Similarly I could download any png image on the hard drive, which is obviously not desired.
For a reason the thumbnails directory must be detached from the server root, so I guess I can not use something like string filePath = HostingEnvironment.MapPath($"~/Images/{id}.png");
To avoid the problem I could trim starting dots or check the incoming id for special characters, but it does not feel like the right way to fight it. I wonder if better practices exist.
Trimming starting dots is not enough, consider an input similar to foo/bar/../../../outside.png.
You should validate the id parameter to only contain say letters, or even better, only numbers. You can achieve complex validation through validation attributes or model validation, both are basically the same. The point is that a user should not be able to enter any special characters, which would effectively mitigate the path injection threat.

Iterating over IEnumerable in view does not print anything

I am trying to print out multiple images using a foreach loop in the view and passing in an IEnumerable<Image> through the model.
My problem is that the foreach loop doesn't display the images at all, and I have no idea what I am doing wrong. I've tried this about 16 different ways and I am still not getting anything other than a broken image link or nothing at all.
Will someone please take a look and see if they can figure out what I am doing wrong? It's probably something very simple and I'm just missing it.
Here is my Controller:
public ActionResult UploadCommission(CommissionViewModel model)
{
List<Image> fileNames = new List<Image>();
//loop through multiple files
foreach (HttpPostedFileBase file in model.Files)
{
//get file names
string filename = System.IO.Path.GetFileName(file.FileName);
//save files
file.SaveAs(Server.MapPath("~/Content/" + filename));
string filepathtosave = "~/Content/" + filename;
fileNames.Add(new Image()
{
FilePath = filepathtosave
});
}
model.ImageFilePaths = fileNames;
return RedirectToAction("ViewComm", model);
}
And here's my View that displayed the information:
#foreach (CapstoneProject.Models.Image i in Model.ImageFilePaths)
{
<img src="#Url.Content(i.FilePath)" />
}
#Model.Title
#Model.Price
#Model.Limit
#foreach (string tag in Model.Tags)
{
<p>#tag</p>
}
#Model.Description
If you need more information, please let me know.
You are using RedirectToAction; according to the docs:
Returns an HTTP 302 response to the browser, which causes the browser to make a GET request to the specified action.
When you pass that model when redirecting to an action, that data will be lost through the redirection action. What you probably want to do instead is make sure you pass the image URLs in the redirect URL or not use a redirect at all (just render a view)
There's really not enough to work with here to effectively answer your question, but there's nothing obviously wrong with the code you've provided. However, in order for any Image instances to be added to the list they must have been posted in the first place (i.e., if model.Files itself is empty, then so will be your IEnumerable<Image>.
To that end, there's two things you should check:
Ensure that your form has accept="multipart/form-data" on it. Otherwise, uploads will not be posted.
Ensure that your file upload field names are such that they'll bind to the model property on post. In your scenario here, they would need names like Files[N], where N is the index.

Getting the thumbnail image from a Web page

I have C# code for fetching images from URLs like http://i.imgur.com/QvkaduU.jpg but how would I fetch the image from Web pages like this:http://imgur.com/gallery/QvkaduU?
Is there any "easy" way to do this or I will have to fetch the HTML and construct a C# parser that looks in HTML for images that are bigger than all the others?
Let me clear this up. If you paste http://imgur.com/gallery/QvkaduU (HTML version) into for example Facebook's status update field it will find the main image and make a thumbnail out of it, this is exactly the behavior I'm looking for. The question is, how is this done? Do I have to write my own HTML parser or is there an easy way to get this?
There is no easy way to get a "good" thumbnail image for an arbitrary URL.
Facebook's algorithm for doing so is fairly complex. Page developers are able to give it a hint by adding various meta tags to the <head>, including:
<meta property="og:image" content="http://url_to_your_image_here" />
or
<link rel="image_src" href="http://www.code-digital.co.uk/preview.jpg" />
(more on this)
... so if you wanted to replicate Facebook's algorithm, you would need to fetch the page source, parse it for any "hints" like the one above (you'd better check that I haven't missed any other "hint" formats), and come up with a fallback algorithm if the page doesn't include one of those.
A more realistic solution would be to use someone else's URL -> thumbnail system.
If you like Facebook's version, I think you should be able to request Facebook's thumbnail for a given URL via their API.
Other services which offer this sort of thing are:
http://webthumb.bluga.net/home (not free)
http://immediatenet.com/thumbnail_api.html (free, may have restrictive TOS)
https://www.google.com/search?q=get+thumbnail+for+url
If the QvkaduU part is always the same between the html page and the image, could you just do a string replacement?
"http://imgur.com/gallery/QvkaduU".Replace("imgur.com/gallery","i.imgur.com") + ".jpg";
I would fetch the whole HTML source and put all <img ... src="..."> parameters as well as < ... style="... background-image: ...;"> css inline properties using regex and try to download all files behind the links temporary. Then I would (try to convert it to Bitmap and) check the pixel size, the largest picture should be the picture you want.
Google might help you how to check pixel size and convert any images.
The regex to get all image links from a HTML source should be
<img[^>]+src=\"([^"]+)\".*?>|<[^>]+style=\"[^"]*background-image:\s*url\(\s*'?([^')])\s*'?)\s*;.*?> (not tested, but pretty sure)
The result will be in the 2nd or 3rd group index, also don't forget to prefix the current url on relative links.
You're already on the right track, yes the most reliable way would be to fetch the HTML, parse it and look for images, you would then rank the images based on position and size. For instance, if the first image you find is big enough to make the thumbnail, then cool, if however it is small, you go to the next image, etc. It would be most advisable to use an image plugin like Timthumb (I think I've seen an ASP.NET version sometime) and cache the images such that once you've looked up the thumbnail to represent a website, you can call the image(s) from the catch instead.
Can you try to do something like this?
public void ProcessRequest(HttpContext context)
{
{
// load here the image
....
// and send it to browser
ctx.Response.OutputStream.Write(imageData, 0, imageData.Length);
}
}
You can also try what they are talking about here. I tried it and it worked like a charm.
http://www.dotnetspider.com/resources/42565-Download-images-from-URL-using-C.aspx
can you try this
public Bitmap getImageFromURL(String sURL)
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(sURL);
myRequest.Method = "GET";
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(myResponse.GetResponseStream());
myResponse.Close();
return bmp;
}
gotten from
How to get an image to a pictureBox from an URL? (Windows Mobile)

How does Response.Redirect calculate the URL for "~/folder1/folder2/some.aspx"

This might sound like a trivial problem but for some reason it is not.
Instead of needing to redirect
Response.Redirect("~/folder1/folder2/some.aspx")
I need the location as if it behaved like
string navigatingUrl = Response.Redirect("~/folder1/folder2/some.aspx")
Trying to replicate this I started with
string navigatingUrl = new Uri(HttpContext.Current.Request.Url,
new Uri("~/folder1/folder2/some.aspx", UriKind.Relative));
This instead generates "http://www.fullRequestUrl/~/folder1/folder2/some.aspx"
Edit: Well I've found out why I absolutely hate the URL API from Microsoft. I wish hellfire to whoever wrote this line of code
else if (uriKind == UriKind.Relative)
{
// Here we know that we can create an absolute Uri, but the user has requested
only a relative one
e = GetException(ParsingError.CannotCreateRelative);
}
What would possess someone to throw an error like that? This single if statement completely destroys the API.
I think you are looking for Control.ResolveUrl(). Typically you would probably use the method found on your Page object (if you are using WebForms).
Stealing from Get absolute url for a file in my asp.net project to include HTTP// etc for use externally? the only absolute way to do this is:
string url = Request.Url.GetLeftPart(UriPartial.Authority)
+ VirtualPathUtility.ToAbsolute(relativePath)
Response.Redirect(Page.ResolveUrl("~/folder1/forlder2/some.aspx"), false);

Categories

Resources