Iterating over IEnumerable in view does not print anything - c#

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.

Related

PHP: is_uploaded_file only seems to know how to handle 1 file per restart of application?

In C# I have code that uploads a file Async to a php file, then in the PHP file I assign a unique ID (given by the C# code), then store the file in a database. This can run multiple times BUT it only seems to be working with the very first file that gets uploaded, and not the subsequent.
Maybe (is_uploaded_file($_FILES['file']['tmp_name']) only knows how to reference the VERY FIRST file it receives and doesn't know to clear it from memory? So the other files it receives shortly later is called (is_uploaded_file($FILES['file2']['tmp_name'] or something. Just a shot in the dark.
I'm not going to post a bunch of code because my code is very simple and is not a problem with it as far as I am aware, this is the only reason this error might be happening as far as I know.
EDIT: Fine, its not that simple but here is code:
C#
foreach (MailItem email in Globals.ThisAddIn.Application.ActiveExplorer().Selection)
{
string email_id = ArchiveEmail(email);
if (chkBoxSyncEmail.Checked)
{
foreach (Attachment atch in email.Attachments)
{
try
{
if(AttachmentsBeingSent.Contains(atch.FileName))
{
//Sending attachment.
string filePath = Path.Combine(#"", (email_id + atch.FileName)); //We add the unique email_id to the beginning of the filename, it is always 13 chars long so we can pull the unique id off later with ease.
atch.SaveAsFile(filePath); //Save as file
WebClient wc = new WebClient();
await wc.UploadFileTaskAsync(new Uri("https://xxxx.com/xxxx/xxxx/xxxx/upload_attachment.php"), "POST", filePath);
MessageBox.Show(atch.FileName + " Uploaded successfully");
if (File.Exists(filePath))
{
File.Delete(filePath);
}
}
}
PHP
<?php
include('../include/xxx.php');
if (is_uploaded_file($_FILES['file']['tmp_name']))
{
global $xxx;
$uploaddir = 'xxxxxxxx/'; // Relative Upload Location of data file, if its empty it should place in this location.
$given_email_ID = substr(($_FILES['file']['name']),0,13); //Take first 13 chars off from beginning and that is our email_ID.
$fileName = substr(($_FILES['file']['name']),13); //This should be our filename and extension intact. Still need to add a unique_ID to this one so it doesn't get overwritten in file system.
$unique_ID = uniqid();
$newName = $unique_ID.$fileName;
$download_loc = ($uploaddir.$NewName);
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploaddir.$newName))
{
$xxx->query("
INSERT INTO attachments(
email_id,
file_name,
download_loc) VALUES (
'" . $given_email_ID . "',
'" . $newName . "',
'" . $download_loc . "'
);
");
}
}
QUERY (in PHP)This only gives me one result! I should have at least multiple. Only one thing gets entered in the table back in the other PHP script.
<?php
$attachments = $xxxx->query("
SELECT *
FROM attachments
");
if($attachments->num_rows > 0) {
while ($row = $attachments->fetch_assoc()) {
echo $row['email_id'].' ';
}
}
?>
As you're sending the files without any html or form directly by C# I verified your C# code a bit now and remarked a fault.
You've to see the principal statements I do, about the notation in C# I might be wrong as I'm not working with it. So it's possible, that you've to adjust my code.
The important point is: you're sending in each loop only one file.
This is your code, generally adjusted to upload several files if available:
foreach (MailItem email in Globals.ThisAddIn.Application.ActiveExplorer().Selection)
{
string email_id = ArchiveEmail(email);
if (chkBoxSyncEmail.Checked)
{
// collecting attachements
array attachements;
foreach (Attachment atch in email.Attachments)
{
if(AttachmentsBeingSent.Contains(atch.FileName))
{
string filePath = Path.Combine(#"", (email_id + atch.FileName)); //We add the unique email_id to the beginning of the filename, it is always 13 chars long so we can pull the unique id off later with ease.
atch.SaveAsFile(filePath); //Save as file
attachements[] = filePath;
}
}
try
{
// if there are any attachements, do upload
if(sizeof(attachements))
{
//Sending attachments.
WebClient wc = new WebClient();
await wc.UploadFileTaskAsync(new Uri("https://xxxx.com/xxxx/xxxx/xxxx/upload_attachment.php"), "POST", attachements);
...
}
}
}
}
I removed a few lines with some logic which was prepared to send only one file. If you send multiple files at once, things are working different and you can't handle a feedback for every single file, at least not in the kind like you coded.
You've to make two small changes in your code:
the name in the input-field of the form has to be an array to take several file and it has to be noted / announced that upload of several files is possible:
<input type="file" name="attachements[]" multiple="multiple" id="attachements" />
The array of files is built when the square brackets are used [] after the field-name.
multiple can be noted in several versions, probably it's enough just to use the word inside the html for the input-field without any assignment, the notation I used above comes from the old xml-syntax, you also can leave the assignment empty or use "true" as value.
The php-code for handling a single file has to be moved into a loop to handle all files. Before changing the form you won't be able to see more than one file in the incoming array $_FILES. According to the input-field above all files will be available in the variable $_FILES['attachements'].
Furthermore you've to adjust the form-element perhaps. If you handle the upload by the same site respectively file where the form is located you can just note it like this and leavinng action empty:
<form action="" enctype="multipart/form-data" method="post">
If you handle the upload on a different site just enter the filename in the action like this:
<form action="url/to/file/handle-upload.php" enctype="multipart/form-data" method="post">
Here you find an approach to realize it with ajax: PHP Handling file uploads
Here you find a video with a solution that is building a few small features around the whole approach.
Here you find the input-field with type file in the html5-standard.

Handle post (from iOS) with image in asp.net server

First, the question briefly:
What I should write in the action parameters for handling the image sent and how to handle data to get the image of it?
What I did is:
Image in iOS converted to NSData (which is a Byte array data if I'm not wrong.
Using AFNetworking to post: to strings that I need in params dict and the image data in
[formData appendWith...].
On the server side, how should my action look like?
Currently it's:
Public JsonResult HandleData (string x, string y, ???????????) {}
The to strings will come from the parameters dictionary but what do I need to do to get the image data and reverse it back to real image?
Thank you so much in advance!
So.. The solution was very simple use in HttpPostedFileBase.
Just added another parameter to my method (HttpPostedFileBase file) and then:
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/Content/images"), fileName);
file.SaveAs(path);
}
Hope it will be useful for poeple like me that are drowning in much more complex solution out there...

How to get content of rendering programmatically?

I am attempting to write a method that will output the content (i.e. HTML) for any renderings that happen to exist within a specific placeholder. The goal is to pass in a Sitecore.Data.Items.Item and the placeholder key that i'm interested in, and the method should return the rendered content.
The issue with this seems to be that there is no page context established, and therefore calling RenderControl() is throwing a null reference error in the GetCacheKey() method of the Sublayout.
Is anyone aware of a way to render a Sublayout or XSLT rendering programmatically?
Here's what I've got so far:
private string GetPlaceholderContent(Item item, string placeHolder)
{
StringWriter sw = new StringWriter();
using (HtmlTextWriter writer = new HtmlTextWriter(sw))
{
foreach (RenderingReference renderingReference in item.Visualization.GetRenderings(Sitecore.Context.Device, false))
{
if (renderingReference.Placeholder == placeHolder)
{
// This ensures we're only dealing with Sublayouts
if (renderingReference.RenderingItem.InnerItem.IsOfType(Sitecore.TemplateIDs.Sublayout))
{
var control = renderingReference.GetControl();
control.RenderControl(writer); // Throws null reference error in GetCacheKey()
}
}
}
}
return sw.ToString();
}
It is almost 8 years since the question was originally asked, and it turn to be Uniform - rendering any item/placeholder fragment!
Yes, it cuts the item you supply into placeholders/renderings:
The next step is to produce markup (for every possible data source out there):
That content is published into CDN and browser picks which version to load = personalization works!
In other words, the question you've asked turned into a cutting-edge product that can do so much more on top of that!
You could reverse-engineer the Uniform assemblies to see how they actually do that ;)
In my opinion, the best way to programmatically render a Sublayout is to use a repeater, and put a <sc:Sublayout> tag in the <ItemTemplate>.
From there you only have to do one or both of the following:
Set the DataSource property of the <sc:Sublayout> to be the string representation of the desired item's GUID (i.e. the data source for the sublayout, if any)
Set the Path property of the <sc:Sublayout> to be the path to the Sublayout that you wish to render.
The server/sitecore will handle the rest.

Render image from byte[] that is not in the DB in ASP.NET MVC3

This is a variation on a question that has been asked here several times. One example: Display an image contained in a byte[] with ASP.Net MVC3. The question is how to render an image from a byte array.
In all those questions, there is an Action similar to one of the answers in the link I provided above:
public FileContentResult Display(string id) {
byte[] byteArray = GetImageFromDB(id);
return new FileContentResult(byteArray, "image/jpeg");
}
With an image tag similar to this:
<img src="#Url.Action("Display", new { id = Model.Id })" />
This is done because it's not possible to send a byte array through a GET request, so just the id is sent allowing a lookup in the Action method. I get this part, it's not the problem. What I'm trying to do is create a 'Preview' page, where they can check their work before saving in the database. They can see the layout of the Title, Text and Image and decide whether to save, or go back and Edit some more. Therefore, the 'GetImageFromDB(id)' part won't work, since the object has not been saved yet to the database.
Is there any way to accomplish this, or do I just have to save the byte array temporarily in the database and access it that way for the Preview page?
You need to store the uploaded file somewhere on the server if you want to show it later (as a preview or full size image). Whether it is the database or the file system it is up to you. So once the file is uploaded you could store it as a temporary file on some location on the server by renaming it using some unique Guid and return this Guid to the client so that it can create an action link to a preview controller action passing the Guid which will fetch the file from the temporary location and stream it to the client.

how to show image not found in Asp.net MVC

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.

Categories

Resources