Error when Uploading image in ASP.NET MVC 3.0 - asp.net-mvc

On the local machine the code below works fine, but when hosted on remote server it doesn't seem to find the image file. I created the Image folder and gave it read/ write permissions as well
// --------------------------------------------
Error
Server Error in '/' Application.
Could not find file 'IdImage.jpg'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.IO.FileNotFoundException: Could not find file 'IdImage.jpg'.
Code is as below
// ---------------------------------------------
[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/Images/Photo"), fileName);
file.SaveAs(path);
}
return RedirectToAction("Index");
}

This looks very much like a permission problem. You said that you have created the Images folder and gave it read/write permission, but from what I can see in your code you are attempting to store the image inside a subfolder called Photo. So make sure you have created this folder as well and given read/write permissions to it as well. Also make sure that you are giving those permissions to the correct account - the one that's configured in IIS to run the application pool in which your application is hosted.

I use this code
[HttpPost]
public ActionResult Upload(System.Web.HttpPostedFileBase file)
{
string filename = Server.MapPath("~/files/somename");
file.SaveAs(filename);
return RedirectToAction("Index");
}
in view
#{
ViewBag.Title = "Upload";
}
<h2>
Upload</h2>
#using (Html.BeginForm(actionName: "Upload", controllerName: "User",
method: FormMethod.Post,
htmlAttributes: new { enctype = "multipart/form-data" }))
{
<text>Upload a photo:</text> <input type="file" name="photo" />
<input type="submit" value="Upload" />
}

Related

Select folder in ASP.NET MVC application to upload files

If I want upload a file it's simply:
Razor
#Html.TextBoxFor(m => m.File, new { type = "file" })
or
Html
<input type="file">
But, If I want select a folder to upload all files than contains, is it possible?
Something like:
Razor
#Html.TextBoxFor(m => m.Folder, new { type = "folder" })
Showing a "select folder dialog".
You can't do that when using #Html.TextBoxFor. There may be another way to upload a folder, but I don't know of it.
However, you can change the file upload dialog to upload multiple files at once, which is essentially the same thing. Here is a tutorial showing how.
Essentially, you need to add the following attribute to your file upload input:
#Html.TextBoxFor(m => m.File, new { type = "file", #multiple = "multiple" })
You also need to add the multpart/form-data attribute to your Razor code to generate the form. Here is an example from that tutorial:
#using (Html.BeginForm("UploadFiles", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
At this point, you can select multiple files to upload. You can easily open the folder, hit CTRL+A to select all, then hit upload to upload the entire folder at once.
Please note that you'll need to modify the controller action to accept multiple files at once.
EDIT: Here is an example on how to handle this in your controller action, from the previously mentioned tutorial. Note that your parameter is an array of HttpPostedFileBase objects, each one representing a file you upload. Then, you iterate through each and save it.
[HttpPost]
public ActionResult UploadFiles(HttpPostedFileBase[] files)
{
//Ensure model state is valid
if (ModelState.IsValid)
{ //iterating through multiple file collection
foreach (HttpPostedFileBase file in files)
{
//Checking file is available to save.
if (file != null)
{
var InputFileName = Path.GetFileName(file.FileName);
var ServerSavePath = Path.Combine(Server.MapPath("~/UploadedFiles/") + InputFileName);
//Save file to server folder
file.SaveAs(ServerSavePath);
}
}
}
return View();
}

MVC5 : The resource cannot be found

I am fetching data from a table and displaying it. Every row in the webpage will have a edit hyperlink. That pops up a edit window for respective row. The contents of the pop up are replaced by the #Html.Partial() function. now the form gets submitted from the Partial view. The Interesting fact is first time I edit any row it works fine. However the second time I am getting the following error:
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Edit
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.7.2623.0
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "SerialNumber,ProjectName,Nature,Phase,StartDate,EndDate,ProjectLead,LeadAlias,Onsite,OffShore,ProjectDetail,EditedBy,CreatedBy")] ProjectModel projectModel)
{
projectModel.EditTime = DateTime.Now;
if (ModelState.IsValid)
{
db.Entry(projectModel).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(projectModel);
}
The form gets submitted using the following button:
<input type="submit" value="Save" class="btn btn-default" formaction="Edit" formmethod="post" />
Please let me know if anything else do you need. Thanks in advance.
#shyju 's answer really helped I changed the formaction and it worked

Get full path from view in MVC .net

Im trying to upload a picture in a MVC app build on .net
I made a button :
#Html.EditorFor(model => model.Imagen,
new { htmlAttributes = new{ #class = "input", #type="file" } })
But it only gets the name of the picture. I read thats because of security reasons, so what is the simplest way of get the full path of my picture?
I can use anything (.net framework)
The uploaded file doesn't have a path until you save it somewhere. Your Action should receive an HttpPostedFileBase object from the post which you can use to do this.
A simple example:
[HttpPost]
public JsonResult Upload(HttpPostedFileBase upload)
{
var filePath = System.IO.Path.Combine(#"C:\uploads\", upload.FileName);
upload.SaveAs(filePath);
}

Provider hosted asp.net mvc app upload file

I am trying to create a simple post in which I am also attaching an image using Provider Hosted App on Sharepoint online, and I am not able to get SPHostUrl at Controller in HttpContext.Request, I mean SPHostUrl is missing in HttpContext.Request.
[HttpPost]
public ActionResult Contact(SimplePostModel model,HttpPostedFileBase file)
{}
View
#using (Html.BeginForm("Contact","Home",null,FormMethod.Post,new { enctype= "multipart/form-data"}))
The question is if I am sending this part new { enctype= "multipart/form-data"} in the above mentioned statement of View, I am not able to get SPHostUrl parameter in HttpContext.Request.
If I am not sending the html attributes then I am able to get SPHostUrl parameter in HttpContext.Request. and without html attributes I am also not able to upload a file.
Thanks in Advance for your help.
I have solved the issue,by changing some piece of code on in the Razor View.
#using (Html.BeginForm("Contact","Home",null,FormMethod.Post,new { enctype= "multipart/form-data"}))
Instead of null for object route values I send the spHosturl like below.
#using (Html.BeginForm("Contact","Home",new { SPHostUrl = spUrl },FormMethod.Post,new { enctype = "multipart/form-data" }))
the spUrl value comes like below
#{
var spUrl = Request.QueryString["SPHostUrl"];
}
I hope this will help for new sharepoint online developers

Upload Picture to Windows Azure Web Site

I have an ASP.NET MVC 4 app that i want to deploy to Windows Azure. A part of this app involves uploading a picture. When the picture is uploaded, I want to store the picture in a directory located at /pictures/uploaded.
My question is, how do I upload a picture to a relative path within my app hosted on Windows Azure? Up to this point, my app has been hosted in a Virtual Machine. I was able to do the above by using the following:
string path = ConfigurationManager.AppSettings["rootWebDirectory"] + "/pictures/uploaded;
// Get the file path
if (Directory.Exists(path) == false)
Directory.CreateDirectory(path);
string filePath = path + "/uploaded" + DateTime.UtcNow.Milliseconds + ".png";
filePath = filePath.Replace("/", "\\").Replace("\\\\", "\\");
// Write the picture to the file system
byte[] bytes = GetPictureBytes();
using (FileStream fileStream = new FileStream(filePath, FileMode.Create))
{
fileStream.Write(bytes, 0, bytes.Length);
fileStream.Flush();
fileStream.Close();
}
Currently, ConfigurationManager.AppSettings["rootWebDirectory"] points to an absolute path. I belive this is where my problem lies. I can't figure out how to switch all of this to a relative path.
Thank you!
Here is my as easy as it comes description of how to set this up in azure.
http://geekswithblogs.net/MagnusKarlsson/archive/2012/12/02/how-to-use-azure-storage-for-images.aspx
//Edit; heres the complete example from my blog(if the blog dies).
yourViewName.cshtml
#model List<string>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<form action="#Url.Action("Upload")" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file1" />
<br />
<label for="file">Filename:</label>
<input type="file" name="file" id="file2" />
<br />
<label for="file">Filename:</label>
<input type="file" name="file" id="file3" />
<br />
<label for="file">Filename:</label>
<input type="file" name="file" id="file4" />
<br />
<input type="submit" value="Submit" />
</form>
#foreach (var item in Model) {
<img src="#item" alt="Alternate text"/>
}
Your controller action
public ActionResult Upload(IEnumerable<HttpPostedFileBase> file)
{
BlobHandler bh = new BlobHandler("containername");
bh.Upload(file);
var blobUris=bh.GetBlobs();
return RedirectToAction("Index",blobUris);
}
Your model
public class BlobHandler
{
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
private string imageDirecoryUrl;
/// <summary>
/// Receives the users Id for where the pictures are and creates
/// a blob storage with that name if it does not exist.
/// </summary>
/// <param name="imageDirecoryUrl"></param>
public BlobHandler(string imageDirecoryUrl)
{
this.imageDirecoryUrl = imageDirecoryUrl;
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference(imageDirecoryUrl);
// Create the container if it doesn't already exist.
container.CreateIfNotExists();
//Make available to everyone
container.SetPermissions(
new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
});
}
public void Upload(IEnumerable<HttpPostedFileBase> file)
{
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference(imageDirecoryUrl);
if (file != null)
{
foreach (var f in file)
{
if (f != null)
{
CloudBlockBlob blockBlob = container.GetBlockBlobReference(f.FileName);
blockBlob.UploadFromStream(f.InputStream);
}
}
}
}
public List<string> GetBlobs()
{
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference(imageDirecoryUrl);
List<string> blobs = new List<string>();
// Loop over blobs within the container and output the URI to each of them
foreach (var blobItem in container.ListBlobs())
blobs.Add(blobItem.Uri.ToString());
return blobs;
}
}
Data and images are not meant to be stored in website directory. That's why there is the Azure Blob Storage.
Azure works by copying the website out to an instance, so if more than one instance exists then uploaded images (which are stored local to the instance) will become out of sync, you will even loose images if there are conflicts.
If you really want to do it the line below will give you what you want:
string path = Server.MapPath("~/pictures/uploaded");
There are some good answers here already that tell you exactly how to do what you need. Allow me to propose an alternative if you don't mind.
Personally, to solve problems such as yours, I turn to Azure Blob Storage. Blob storage is an extremely cheap and fast method of storing binary files (in a folder type structure) completely separate from the VM your cloud service is currently running on.
This will allow you some additional freedom when migrating or developing against your existing application since you don't have to migrate your uploads along with each deployment. Blob storage files are also triple-replicated across multiple Azure datacenters at no additional cost to you and are much more fault tolerant than your deployment VM.
Moving to Blob Storage will also allow you to access your files when your site is offline or your VM is down.
You are no longer operating in the realm of shared computing where all resources must exist on the same machine. Azure was built for scalability and separation of resources. Blob storage was designed specifically for what you are trying to do here.
string path = HostingEnvironment.MapPath(#"~/pictures/uploaded");

Resources