I am developing CMS for a website using MVC 5 and Entity Framework. I have an edit form for editing the events added in the database table. I am uploading the image related to Event in a server folder and storing its URL in database.
Now I want to replace the
#Html.EditorFor(model => model.Image_Url, new { htmlAttributes = new { #class = "form-control" } })
with a input with type File, so that anyone can change the image while editing the Event information. for this I have added following.
A Picture Class
public class Pictures
{
public HttpPostedFileBase File { get; set; }
}
for File Uploading in Edit Action Method of controller
if (picture.File.ContentLength > 0)
{
var fileName = Path.GetFileName(picture.File.FileName);
var path = Path.Combine(Server.MapPath("~/assets/uploads/events/"), fileName);
picture.File.SaveAs(path);
filePath = "~/assets/uploads/events/" + fileName;
}
and finaly in Edit view
<input type="file" id="File" name="File" class="form-control" />
The above logic work perfectly fine when used in Create action method, but when I use the same in edit action method the Null reference exception occur. While debugging I found that the picture.File parameter is null at line if (picture.File.ContentLength > 0).
This is working fine in Create but in Edit action method it returns null.
Any Help on this issue?
I have done it by using Request.Files. below is my code in controller Edit action method.
foreach(string fileName in Request.Files)
{
HttpPostedFileBase file = Request.Files[fileName];
fName = file.FileName;
if (file != null && file.ContentLength > 0)
{
var orgDirectory = new DirectoryInfo(Server.MapPath("~/assets/uploads"));
string pathString = System.IO.Path.Combine(orgDirectory.ToString(),"events");
var fileName1 = Path.GetFileName(file.FileName);
bool isExists = System.IO.Directory.Exists(pathString);
if(!isExists)
{
System.IO.Directory.CreateDirectory(pathString);
}
var path = string.Format("{0}\\{1}", pathString, file.FileName); //pathString + file.FileName;
file.SaveAs(path);
}
}
This issue could occur because of general security rules for the <input type="file" /> as you can't set a value for it. So I think the only thing you can do is a create separate view for the re-creating the image for the profile, and each time user sends a picture to you treat is a new one.
Related
I have an ActionLink on my view page which opens a pdf drawing. The drawing files opens without issue but it then updates the page to the Html link. Is there a way to prevent that so the original page remains static and doesn't change?
Table view:
<td>
#if (item.DrawingNumber.Contains("CAD") || (item.DrawingNumber.Contains("DRG")))
{
#Html.ActionLink("PDF", "OpenDrawingPDF", new { DNumber = item.DrawingNumber })
}
</td>
Controller code:
public void OpenDrawingPDF(string DNumber)
{
string Path = #"\\Ser1\Company\10 - Production\Production Drawings\CAD pdf\";
string Folder = DNumber.Substring(4,2) + #"\";
// Open the pdf file
System.Diagnostics.Process.Start(Path + Folder + DNumber + ".pdf");
}
Perhaps the easiest solution is to simply open the pdf in a new tab. You can do that by adding an additional parameter to the ActionLink method:
<td>
#if (item.DrawingNumber.Contains("CAD") || (item.DrawingNumber.Contains("DRG")))
{
#Html.ActionLink("PDF", "OpenDrawingPDF", new { DNumber = item.DrawingNumber }, new { target = "_blank" })
}
</td>
I'm doing some integration with a third party form builder software that allows the form to be posted to our own server. The form data and files are then saved to a DB. The issue is when the form contains multiple file upload fields, Request.Files is always empty.
Using Fiddler, I can see the binary files coming through. The only thing that I can think of is that the field name contains brackets in them (because it's being sent as an array) and so the model binder can't bind it properly? The field names that are coming through are tfa_20[0] and tfa_20[1].
Code-wise, it's pretty standard stuff:
var data = new Submission()
{
ConfigurationDetailId = configDetail.Id,
SubmitterEmail = submitterEmail,
SubmissionData = Request.Form.AllKeys.Select(k => new SubmissionData()
{
FieldName = k,
FieldValue = Request.Form[k]
}).ToList(),
SubmissionFiles = new List<SubmissionFile>()
};
// process any files uploaded
if (Request.Files.Count > 0)
{
foreach (string field in Request.Files)
{
var uploadedFile = Request.Files[field];
if (!string.IsNullOrEmpty(fileName))
{
data.SubmissionFiles.Add(GetSubmissionFile(uploadedFile, fileName));
}
}
}
Repository.SaveForm(data);
Any help would greatly be appreciated.
Use HttpPostedFileBase in order to get posted file to your action. in case of multiple files,should be used an HttpPostedFileBase[] array.
To Enable uploading in forms, is necessary to add enctype="multipart/form-data" to your form tag. or if you use razor syntax change your beginForm tag to this.
View.cshtml
#using (Html.BeginForm("action","controller", FormMethod.Post, new { #enctype =
"multipart/form-data" }))
{
}
public ActionResult YourAction(HttpPostedFileBase[] files)
{
var data = new Submission()
{
ConfigurationDetailId = configDetail.Id,
SubmitterEmail = submitterEmail,
SubmissionData = Request.Form.AllKeys.Select(k => new SubmissionData()
{
FieldName = k,
FieldValue = Request.Form[k]
}).ToList(),
SubmissionFiles = new List<SubmissionFile>()
};
if (files.Length > 0)
{
foreach (HttpPostedFileBase file in files)
{
var uploadedFile = file;
if (!string.IsNullOrEmpty(file.FileName))
{
data.SubmissionFiles.Add(GetSubmissionFile(uploadedFile, file.fileName));
}
}
}
return View();
}
This question already has answers here:
return both a file and a rendered view in an MVC3 Controller action
(3 answers)
Closed 8 years ago.
I am building an app in ASP.Net MVC, and want to return a View AND offer a download to the user. Is it possible? Right now, I can return a new page using
return View();
offer a file download using:
return File(FilePath, "text", "downloadFileName");
reason for this: There will be a checkbox indicating "if download file". If checked, upon the click of a button the specified content will be displayed on the screen and a download dialog will appear.
Any help is appreciated!
UPDATE:
In the end, I chose to provide a download link in the returned View, which works well for the app now.
Please use like below.
ViewData["text"] = "text that you need to return";
ViewData["FileName"] = "Name of the file that you need to return";
ViewData["Filepath"] = "Path of the file that you need to return";
return View();
In your view you can use them like below
#{
var text = ViewData["text"];
var filename = ViewData["FileName"];
var filePath = ViewData["Filepath"];
}
If you need to done without using ViewData or ViewBage means please follow the below code.
There are 3 steps need to do for it.
Step 1:
Create a model class for it.
My model code
public class FileDetails
{
public string Text { get; set; }
public string FileName { get; set; }
public string Filepath { get; set; }
}
Step 2: Controller code to return view with FileDetails Model.
FileDetails Details = new FileDetails();
Details.Text = "text that you need to return";
Details.FileName = "Name of the file that you need to return";
Details.Filepath = "Path of the file that you need to return";
return View("ViewName", Details);
Step 3: Your View must contain the FileDetails model Header. like Below
#model YourProjectName.Models.FileDetails
The above code is must be at top of your view page where you need to use those details.
My View code
#{
var text = Model.Text;
var filename = Model.FileName;
var filePath = Model.Filepath;
}
In my MVC(4) application, I'm fetching the image files from the local directory and displaying it in the browser.
I've a model to store the details,and a controller to get the files and a view to display them.
Model
public class ImageModel
{
List<string> _images = new List<string>();
public ImageModel()
{
_images = new List<string>();
}
public List<string> Images
{
get { return _images; }
set { _images = value; }
}
}
Controller
public ActionResult Index()
{
var imageFiles = new ImageModel();
imageFiles.Images.AddRange(Directory.GetFiles(#"c:\mypath"));
return View(imageFiles);
}
View
#for (int imgIndex = 0; imgIndex < Model.Images.Count; imgIndex++)
{
<div >
<img src = #Model.Images[imgIndex] alt="Image" />
</div>
}
But I can not view the images in the browser, its showing empty boxes with alt.
What did I miss here? Should I create a virtual directory instead of physical location.
First, local files require the file:// URI scheme. You seem to use the native file path as img src.
But the browser security model forbids the use of local source from inside a page served by a web server (http://, https:// protocols).
To fix your situation, the implement a controller that take the desired image file name as parameter, and serve its content using the File() action.
The problem is your path names. This might help:
Controller:
public ActionResult Index()
{
var imageFiles = new ImageModel();
imageFiles.Images.AddRange(System.IO.Directory.GetFiles(#"C:\wherever\files\are\"));
for (int i = 0; i < imageFiles.Images.Count; i++)
{
// get rid of the fully qualified path name
imageFiles.Images[i] = imageFiles.Images[i].Replace(#"C:\wherever\files\are\", "");
// change the slashes for web
imageFiles.Images[i] = imageFiles.Images[i].Replace('\\','/');
}
return View(imageFiles);
}
View:
#for (int imgIndex = 0; imgIndex < Model.Images.Count; imgIndex++)
{
<div >
<img src = "#Model.Images[imgIndex]" /> <!-- put the file in quotes -->
</div>
}
looking at the code snippet, it seems to me that you forgot to surround the path with quotes
<img src = "#Model.Images[imgIndex]" alt="Image" />
but looking at the overall code, i would recommend to use relative paths.
UPD:
For a more detailed explanation, i would recomentd this blog post
I've been asked to see if it's possible to prevent the Content directory from appearing as part of the url in an Asp.Net MVC 3.0 application. For example at present when I want to view an image in the sub directory of the Content folder the url is as follows:
http://localhost:[port]/Content/sub/test.bmp
While we are looking to display it simply as follows:
http://localhost:[port]/sub/test.bmp
Test.bmp will still physically exist in the sub directory of the Content folder on the server we just want to hide the Content part.
Any suggestions? I can see ways of masking controllers but not directories.
You could write a controller action which will take as an argument the filename and serve it from the sub directory. Then configure a route for this controller action so that it is accessible with sub/{filename}.
Solution is as follows (this is just the barebones code at the moment and needs to be tidied up):
Added this route to Global.asax :
routes.MapRoute("Content",
"{dir}/{file}",
new { controller = "Content", action = "LoadContent"});
Added this controller to handle the request:
namespace demos
{
public class ContentController : Controller
{
public ActionResult LoadContent(string dir, string file)
{
string fileName = Server.MapPath(Url.Content("~/Content/" + dir))
fileName += "\\" + file;
// stream file if exists
FileInfo info = new FileInfo(fileName);
if (info.Exists)
return File(info.OpenRead(), MimeType(fileName));
// else return null - file not found
return null;
}
private string MimeType(string filename)
{
string mime = "application/octetstream";
var extension = Path.GetExtension(filename);
if (extension != null)
{
RegistryKey rk = Registry.ClassesRoot.OpenSubKey(extension.ToLower());
if (rk != null && rk.GetValue("Content Type") != null)
mime = rk.GetValue("Content Type").ToString();
}
return mime;
}
}
}