Photo Upload Problem in ASP.NET MVC My Blog Project - asp.net-mvc

When I upload a photo, the page just refresh, not upload the photo in ASP.NET MVC My Blog Project. I looked the solution in Stack OverFlow but I didn't handle this problem. I don't know to write which code here because I am firstly trying to make a blog site in ASP.NET. If you are ask to me whatever code, I publish here quickly. Thanks for cooperation.

Say for example your model is
public class blog
{
public int Id { get; set; }
public string Code { get; set; }
public string Photo1 { get; set; }
}
Here I'm storing the photo in the server (Not in the database)
There goes the controller
public ActionResult BeginUploadPhoto(int Id)
{
var Blog= db.blog.Where(a => a.Id == Id).FirstOrDefault();
return View(Blog);
}
public ActionResult UploadPhoto(int? Id, HttpPostedFileBase Logo)
{
BlogCP = db.Blog.Find(Id);
WebImage img = new WebImage(Logo.InputStream);
if (img.Width > 500)
img.Resize(500, 500);
// to reduce the size upon upload
string extension = Path.GetExtension(Logo.FileName);
// get your photo extenstion
string filename = Guid.NewGuid().ToString();
// rename the upload photo
var path = Path.Combine(Server.MapPath("~/BlogPhoto/"), filename + extension);
// make sure that you create a folder BlogPhoto in your project or you can
//name it anything you like
string savepath = "~/BlogPhoto/" + filename + extension;
BlogCP.Photo1= savepath;
img.Save(path);
// save photo in your server
if (ModelState.IsValid)
{
db.Entry(BlogCP ).Property(r => r.Photo1).IsModified = true;
db.SaveChanges();
return RedirectToAction("Index","Staff");
}
return RedirectToAction("Index");
}
There goes the View
#model ProjectName.Entities.Blog
#{
ViewBag.Title = "BeginUploadPhoto";
}
<div class="container">
#if (Model.Photo1 != null)
{
<img id="Preview" class="img-thumbnail" src=#Model.Photo1/>
}
#using (Html.BeginForm("UploadPhoto", "ControllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
{
#Html.HiddenFor(m => m.Id)
<div>
<a>Select and upload Photo</a>
<input type="file" id="Logo" name="Logo"
<input type="file" id="Logo" name="Logo" accept="image/*" onchange="loadFile(event)">
</div>
<div class="form-group">
<button id="btnUpload"
class="btn btn-sm btn-primary"
formnovalidate="formnovalidate"
data-pdsa-action="upload">
<i class="glyphicon glyphicon-upload"></i>
Upload
</button>
</div>
}
}

Related

Unable to cast object of type 'Microsoft.Asp.NetCore.Http.FormFile' to type 'System.IO.Stream' in Asp.NetCore MVC web app

I am a newbie to Asp.netCore as well as Microsoft Azure. Recently, I am trying to integrate ASP.net Core MVC web app with blob storage.
In the application I upload an file (image) to the azure blob storage, and the URL of the uploaded file is stored in the Microsoft SQL database. The database is connected to the application perfectly and it is working fine too.
I have created an Azure blob storage and I have already created containers and have manually uploaded files to the blob storage. Blob storage also working perfect.
This is the controller class: (I have put the image uploading controllers in the 'HomeController' for the testing purposes
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using WebAppMVC.Data;
using WebAppMVC.Models;
using WebAppMVC.Utilities;
namespace WebAppMVC.Controllers
{
public class HomeController : Controller
{
private readonly UserManager<WebAppMVCUser> _userManager;
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger,UserManager<WebAppMVCUser> userManager)
{
_logger = logger;
/* newly added */
_userManager = userManager;
utility = new BlobUtility(accountName, accountKey);
db = new WebAppMVC_DBContext();
/* newly added */
}
/* newly added */
BlobUtility utility;
WebAppMVC_DBContext db;
string accountName = "_my_Storage_Name";
string accountKey = "My_storage_account_key";
/* newly added */
[Authorize]
public IActionResult Index()
{
/* newly added */
string loggedInUserId = _userManager.GetUserId(User);
List<UserMedium> userMedia = (from a in db.UserMedia where a.UserId.ToString() == loggedInUserId select a).ToList();
ViewBag.PhotoCount = userMedia.Count;
return View(userMedia);
/* newly added */
}
/* newly added */
[Authorize]
public ActionResult DeleteImage(int id)
{
UserMedium userImage = db.UserMedia.Find(id);
db.UserMedia.Remove(userImage);
db.SaveChanges();
string BlobNameToDelete = userImage.ImageUrl.Split('/').Last();
utility.DeleteBlob(BlobNameToDelete, "profilepics");
return RedirectToAction("Index");
}
[Authorize]
[HttpPost]
public ActionResult UploadImage(IFormFile file)
{
if (file != null)
{
string ContainerName = "profilepics"; // container name.
//file = Request.File["file"];
string fileName = Path.GetFileName(file.FileName);
Stream imageStream = file.OpenReadStream();
var result = utility.UploadBlob(fileName, ContainerName, (Stream)file);
if (result != null)
{
string loggedInUserId = _userManager.GetUserId(User);
UserMedium usermedium = new UserMedium();
usermedium.MediaId = new Random().Next();
try
{
usermedium.UserId = Int32.Parse(loggedInUserId);
}
catch
{
Console.WriteLine($"Unable to parse '{loggedInUserId}'");
}
usermedium.ImageUrl = result.Uri.ToString();
db.UserMedia.Add(usermedium);
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
return RedirectToAction("Index");
}
}
else
{
return RedirectToAction("Index");
}
}
/* newly added */
[Authorize]
public IActionResult Privacy()
{
return View();
}
[Authorize]
public IActionResult Media()
{
return View();
}
public IActionResult InformationPortal()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}
This is the View Index.cshtml code: (I am uploading the file from the Index.cshtml) Uploading-Image-from-the-view
#model IEnumerable<WebAppMVC.Models.UserMedium>
<div class="container">
<div class="row">
#using (Html.BeginForm("UploadImage", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="panel panel-warning">
<div class="panel-heading">
<h3 class="panel-title">Upload and save your photo</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<input type="file" name="file" />
<br />
<input type="submit" class="btn btn-warning form-control" value="Save Photo" />
</div>
</div>
</div>
</div>
}
</div>
<br />
<div class="row">
<div class="col-lg-12">
<div class="alert alert-warning">You have #ViewBag.PhotoCount Photos </div>
</div>
#foreach (var item in Model)
{
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#item.ImageUrl">
<img class="img-responsive" src="#item.ImageUrl" style="height: 300px;width:100%;" alt="">
</a>
<a href="#Url.Action("DeleteImage", "Home",new { id = item.MediaId })" class="btn btn-default btn-block">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</a>
</div>
}
</div>
But when I run the app, after uploading the file(jpg image) I am getting the following exception:
This exception comes and application also put into the break mode.
Exception: Click-here-to-see-the-exception
As depicted in the picture, the application is put into the break mode and that exception is thrown at the line 74 of HomeController (The controller I used to control the file upload).
Following is the detailed description of the exception: exception-details
And when I step forward, I am getting this error message on the browser: Exception-error-on-browser
I do not understand the error and Does anybody know how to solve this issue?
Thanks in advance.
Try this function to convert IFormFile to Stream.
public static async Task<Stream> GetStream(this IFormFile formFile)
{
using (var memoryStream = new MemoryStream())
{
await formFile.CopyToAsync(memoryStream);
return memoryStream;
}
}
This will work for you:
IFormFile file;
byte[]? image = Array.Empty<byte>();
if (file != null)
{
await using var memoryStream = new MemoryStream();
await file!.CopyToAsync(memoryStream);
image = memoryStream.ToArray();
}

Displaying List of Uploaded Files

I have a form where users can upload files and then view a list of their uploads. I'm running into two issues:
List of files isn't appearing when page loads. The SQL Query is valid.
When user uploads a file, a NullReferenceException because the file list model isn't being loaded. I'm not sure how to pass this model into view after the upload. Any advice is greatly appreciated.
Controller for fetching list of datasets is below. The controller for uploading datasets is different, of course, but it accepts an HttpPostedFileBase and a datasetName. It only returns ViewBag.error/ViewBag.message.
public ActionResult upload(DatasetViewModel model)
{
List<DatasetDetail> model2 = new List<DatasetDetail>();
var connectionstring = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
using (SqlConnection con = new SqlConnection(connectionstring))
try
{
// Your code
con.Open();
using (SqlCommand cmd = new SqlCommand("", con))
{
cmd.CommandText = "SELECT datasetid, datasetname, timestamp FROM datasets WHERE userid = #userid";
cmd.Parameters.Add("#userid", SqlDbType.Text);
cmd.Parameters["#userid"].Value = System.Web.HttpContext.Current.User.Identity.GetUserId();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
var u = new DatasetDetail();
u.datasetid = reader["datasetid"].ToString();
u.dataset = reader["datasetname"].ToString();
/* u.timestamp = Convert.ToDateTime(reader["TIMESTAMP"]);*/
model2.Add(u);
}
}
}
catch
{
// Catch exception
}
finally
{
// Close the connection
con.Close();
}
model.datasetlist = model2;
return View(model);
}
View:
#model WebApplication12.Models.DatasetViewModel
<div style="width: 320px;">
<h2>Manage Datasets</h2>
Download Excel Template
#using (Html.BeginForm("upload", "Dashboard", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="form-group">
<label>Dataset Name:</label>
<br />
<input type="text" id="datasetname" name="datasetname" />
</div>
<div class="form-group">
<input type="file" id="dataFile" name="upload" />
</div>
<div class="form-group">
<input type="submit" value="submit" class="btn btn-block" />
</div>
}
</div>
<div id="response"></div>
#if (ViewBag.Message != null)
{
<div class="alert alert-success" role="alert">#Html.Raw(ViewBag.Message)</div>
}
#if (ViewBag.Error != null)
{
<div class="alert alert-error" role="alert">#Html.Raw(ViewBag.Error)</div>
}
<div>
#foreach (var u in Model.datasetlist)
{
<b>u.dataset</b>
}
</div>
Relevant Models:
public class DatasetViewModel
{
public List<DatasetDetail> datasetlist { get; set; }
}
public class DatasetDetail
{
public string datasetid { get; set; }
public string dataset { get; set; }
/* public DateTime timestamp { get; set; }*/
}

Upload Image in Asp.Net Core?

I want to upload image in "wwwroot/uploads/img" folder but i get error.I wrote the following code:
Create View :
#model imageuploader.Models.Employee
<form method="post" enctype="multipart/form-data" asp-controller="Employee" asp-action="Create">
<div class="form-group">
<div class="col-md-10">
<input asp-for="FirstName" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<input asp-for="LastName" Class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<input asp-for="ImageName" type="file" Class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<input type="submit" value="Create" />
</div>
</div>
Model :
public class Employee
{
[Key]
public int ID { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public string ImageName { get; set; }
}
Controller
private readonly RegisterDBContext _context;
private readonly IHostingEnvironment _appEnvironment;
public EmployeeController(RegisterDBContext context, IHostingEnvironment appEnvironment)
{
_context = context;
_appEnvironment = appEnvironment;
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Employee emp)
{
if (ModelState.IsValid)
{
var files = HttpContext.Request.Form.Files;
foreach (var Image in files)
{
if (Image != null && Image.Length > 0)
{
var file = Image;
//There is an error here
var uploads = Path.Combine(_appEnvironment.WebRootPath, "uploads\\img");
if (file.Length > 0)
{
var fileName = Guid.NewGuid().ToString().Replace("-", "") + Path.GetExtension(file.FileName);
using (var fileStream = new FileStream(Path.Combine(uploads, fileName), FileMode.Create))
{
await file.CopyToAsync(fileStream);
emp.BookPic = fileName;
}
}
}
}
_context.Add(emp);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
else
{
var errors = ModelState.Values.SelectMany(v => v.Errors);
}
return View(emp);
}
When i click on submit button i get an error (error line is marked), how can i upload image or file in Specified path?
Error:
NullReferenceException: Object reference not set to an instance of an object.
imageuploader.Controllers.EmployeeController+<Create>d__2.MoveNext() in EmployeeController.cs
var uploads = Path.Combine(_appEnvironmen.WebRootPath, "uploads\\img\\");
How can i upload image correctly in Specified path?
I Solved it. I understood i initial bad
_appEnvironment
in Constructor.
With repeated edits, all of the codes in question are currently correct.
Thanks #Shyju user.
Here is how to upload an image in C# Asp.net core Web Application 2.1 MVC:
First I'm assuming you've created a model, added to db and now working in the controller.
I've created a Person model
person model
For create get:
//Get : Person Create
public IActionResult Create()
{
return View();
}
post Action (please see screen shot)
create post action method
Finally the view
Create View
Project Output:
Here is the output of my project

How to pass a complex model back to the controller in asp.net mvc

New to web development.
I have a view that allows user to select an excel file.
When submit "preview" button is pressed file is read and data is sent back to the user to preview the data.
Then I want to be able send the model back to the control for db upload.
(this is the part I'm struggling with).
ViewModel:
public class UploadItemsViewModel
{
public List<Item> Items { get; set; }
public int CompanyID { get; set; }
public Company Company { get; set; }
public HttpPostedFileBase upload { get; set; }
public UploadJournalsViewModel()
{
Items = new List<Item>();
}
}
Controller:
public ActionResult Upload(FormCollection formCollection, int CompanyID)
{
if (Request != null)
{
HttpPostedFileBase file = Request.Files["UploadedFile"];
if ((file != null) && (file.ContentLength > 0) && !string.IsNullOrEmpty(file.FileName))
{
string fileName = file.FileName;
string fileContentType = file.ContentType;
byte[] fileBytes = new byte[file.ContentLength];
var data = file.InputStream.Read(fileBytes, 0, Convert.ToInt32(file.ContentLength));
}
}
UploadItemsViewModel itmViewModel = new UploadItemsViewModel { Company = db.Companies.Find(CompanyID), CompanyID = CompanyID };
return View(itmViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Upload(UploadItemsViewModel itmViewModel, string Preview, string Upload)
{
if (ModelState.IsValid)
{
if (itmViewModel.upload != null && itmViewModel.upload.ContentLength >0)
{
try
{
itmlViewModel.Items = App.Services.ItemsMassUploadFileRead.ReadExcelFile(itmViewModel.upload, db.Companies.Find(itmViewModel.CompanyID));
if (string.IsNullOrEmpty(Preview))
{
foreach (var itm in itmViewModel.Items)
{
itm.StartDate = DateTime.Today;
itm.CompanyID = itmViewModel.CompanyID;
itm.User = null;
itm.Items.Add(itm);
db.SaveChanges();
}
return View();
}
else
{
return View(itmViewModel);
}
} }
catch (Exception ex)
{
ModelState.AddModelError("File", ex.Message.ToString());
return View(itmViewModel);
}
}
else
{
ModelState.AddModelError("File", "Please Upload Your file");
}
}
return View(itmViewModel);
}
View:
#using (Html.BeginForm("Upload", "ItemsUpload", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.CompanyID)
<div class="form-group">
<div class="input-group">
<label class="input-group-btn">
<span class="btn btn-default">
Browse… <input type="file" style="display: none;" accept=".xlsx" name="upload">
</span>
</label>
<input type="text" class="form-control " readonly>
</div>
<span class="help-block">
Please use a provided Excel template
</span>
</div>
<div class="form-group">
<input type="submit" value="Preview" name ="Preview" class="btn btn-default" disabled style="display: none" id="submit"/>
</div>
<div class="form-group">
<input type="submit" value="Upload" name="Upload" class="btn btn-default" id="Upload" />
</div>
<div class="help-block" id="previewHelp" style="display: none">
Preview results and scroll down to upload data to the database.
</div>
if (Model.Journals.Count != 0)
{
table here to preview the upload
}
After clicking the Upload button model comes back without the "items" collection.
The Items list will be always null in the controller, because you don't rendered any input on the View with the name Items

ASP.NET MVC Two file upload, different destinations

I'm trying to upload two different files into two different database fields on same form.
------------------------------------
reportid | name | image | template |
------------------------------------
this is the table look. So I want to upload files to image and template. My model:
public class Report
{
[Key]
public int ReportID { get; set; }
[Required]
public string Name { get; set; }
public byte[] Image { get; set; }
public byte[] Template { get; set; }
}
My Create method in controller:
public ActionResult Create(Report report, HttpPostedFileBase file, HttpPostedFileBase temp)
{
if (ModelState.IsValid)
{
if (file != null && file.ContentLength > 0)
{
using (MemoryStream ms = new MemoryStream())
{
file.InputStream.CopyTo(ms);
report.Image = ms.GetBuffer();
}
}
if (temp != null && temp.ContentLength > 0)
{
using (MemoryStream ms1 = new MemoryStream())
{
temp.InputStream.CopyTo(ms1);
report.Template = ms1.GetBuffer();
}
}
db.Reports.Add(report);
db.SaveChanges();
db.Configuration.ValidateOnSaveEnabled = true;
return RedirectToAction("Index");
}
And part of view concerning uploads:
<div class="editor-label">
<%:Html.LabelFor(model => model.Image) %>
</div>
<div class="editor-field">
<input type="file" id="fuImage" name="file" />
</div>
<div class="editor-label">
<%:Html.Label("Template") %>
</div>
<div class="editor-field">
<input type="file" id="temp" name="temp"/>
</div>
<p>
<input type="submit" value="Create" />
</p>
I'm quite stuck in this since I can not use IEnumerable<HttpPostedFileBase> files as a parameter in Create method because I need to save it in a different field, or can I? How should I approach this? Please help :S
Note: Image upload works fine.
Why not use IEnumerable<HttpPostedFileBase> ? You may use it like this.
[HttpPost]
public ActionResult Create(Report report, IEnumerable<HttpPostedFileBase> files)
{
if (ModelState.IsValid)
{
//Let's take first file
if(files.ElementAt(0)!=null)
{
var file1=files.ElementAt(0);
if (file1!= null && file1.ContentLength > 0)
{
//do processing of first file
}
}
//Let's take the second one now.
if(files.ElementAt(1)!=null)
{
var temp =files.ElementAt(1);
if (temp!= null && temp.ContentLength > 0)
{
//do processing of second file here
}
}
}
//Do your code for saving the data.
return RedirectToAction("Index");
}
EDIT : After seeing your View Markup in your EDIT.
The name of the file input element should be same as the parameter name in your action method. (files in this example)
#using (Html.BeginForm("Create", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<b>File 1</b>
<input type="file" name="files" id="file1" />
<b>File 2</b>
<input type="file" name="files" id="file2" />
<input type="submit" />
}
This code assumes that read ONLY the first 2 entries from the collection.Since you wanted only 2 files, i hardcoded the indexes.
Phil has a nice blog post explaining about it very nicely.

Resources