How to display image in list in MVC? - arrays

I'm a final year student, working on FYP, I have an issue about fetching image that is stored in binary data in database. I tried lots of solutions, I've searched on Google, but not working any solution.
View
#model IEnumerable<PictureServices.Picture>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
<tr>
#foreach (var item in Model)
{
<td>
#{
var base64 = Convert.ToBase64String(item.image);
var imgsrc = string.Format("data:image/jpg;base64,{0}", base64);
}
<img src='#imgsrc' style="max-width:100px; max-height:100px;">
</td>
model
public class Picture
{
public int id { get; set; }
public byte[] image { get; set; }
public string name { get; set; }
}
controller
public class CarServicesController : Controller
{
TestingEntities db = new TestingEntities();
public ActionResult Index()
{
Picture ds = new Picture();
var item = (from d in db.Pictures
select d).ToList();
return View(item);
}

You can convert the byte array to base 64 string and use that as the image source. You can use the Convert.ToBase64String to do so. One thing you must do is a null check before trying to convert the byte array as that could be null.
#model IEnumerable<PictureServices.Picture>
<table class="table table-striped">
#foreach (var r in Model)
{
<tr>
<td>#r.Id</td>
<td>#r.Name</td>
<td>
#if (r.Image != null)
{
var imgSrc = $"data:image/jpg;base64,{Convert.ToBase64String(r.Image)}";
<img src="#imgSrc" alt="#r.Name" />
}
</td>
</tr>
}
</table>
I would also recommend using PascalCasing for C# class properties ( Name instead of name).

Related

Asp.net core database data displayed more often than existing

I'm wondering why my ASP.NET Core MVC Project is listing my data double.
What it should be:
What it gives me:
See the difference?
My Controller (Controller Class - Index()-Method):
[HttpGet()]
public async Task<IActionResult> Index(string id)
{
IQueryable<string> werkeQuery = from m in _context.TestDbSet
orderby m.Id
select m.Id;
var test = from t in _context.TestDbSet
orderby t.Id
select t;
if (!string.IsNullOrEmpty(id))
{
test = (IOrderedQueryable<TestSet>)_context.TestDbSet.Where(x => x.Id == id);
}
var filter = new TestSet
{
Werke = new SelectList(await werkeQuery.Distinct().ToListAsync()),
Liste = await test.ToListAsync()
};
return View(filter);
}
My Model-Class (could there be the error?):
`[Table("Test", Schema = "dbo")]
public class TestSet
{
[Key]
[Display(Name = "Werk")]
[Column("Id")]
public string Id { get; set; }
[Display(Name = "Mitarbeiter ID")]
[Column("M_ID")]
public string M_Id { get; set; }
[Column("Beginn")]
[DataType(DataType.Date)]
public DateTime Beginn { get; set; }
[Column("Ende")]
[DataType(DataType.Date)]
public DateTime Ende { get; set; }
[NotMapped]
public SelectList Werke { get; set; }
[NotMapped]
public List<TestSet> Liste { get; set; }
}`
My View (relevant code: displayed list):
`#model DienstplanAnzeige.Models.TestSet
#{
ViewData["Title"] = "Startseite";
}
<form asp-controller="Home" asp-action="Index" method="get">
<div class="input-group mb-3">
<select class="custom-select" asp-for="Id" asp-items="#Model.Werke">
<option value="" disabled selected>Werk auswählen</option>
</select>
<input type="submit" value="Anzeigen" class="btn btn-outline-secondary" />
</div>
</form>
<table class="table table-hover">
<thead>
<tr>
<th>#Html.DisplayNameFor(model => model.Liste[0].Id)</th>
<th>#Html.DisplayNameFor(model => model.Liste[0].M_Id)</th>
<th>#Html.DisplayNameFor(model => model.Liste[0].Beginn)</th>
<th>#Html.DisplayNameFor(model => model.Liste[0].Ende)</th>
</tr>
</thead>
<tbody>
#foreach(var item in Model.Liste)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.Id)</td>
<td>#Html.DisplayFor(modelItem => item.M_Id)</td>
<td>#Html.DisplayFor(modelItem => item.Beginn)</td>
<td>#Html.DisplayFor(modelItem => item.Ende)</td>
</tr>
}
</tbody>
</table>`
My Context-Class (named "TestContext"):
public class TestContext : DbContext
{
public TestContext(DbContextOptions<TestContext> options)
: base(options)
{
}
public DbSet<TestSet> TestDbSet { get; set; }
}
Can someone help me?
In your controller, since your id property and parameter is in string therefore instead of using == comparison operator you should use Equals(...) method of string class i.e.
if (!string.IsNullOrEmpty(id))
{
test = (IOrderedQueryable<TestSet>)_context.TestDbSet.Where(x => x.Id.Equals(id, StringComparison.InvariantCultureIgnoreCase);
}

Displaying the result set of a Db view in asp.net core view

I am executing a stored procedure from my asp.net core app. The procedure executes a select statement from a db view. The db view inner joins 3 tables. When I execute the following code the result set comes as an int throwing an exception as the razor view expects List, I need to receive it as a list in order to pass it to the razor view and display the table. I would appreciate any help.
ViewModel:
public class ViewModel
{
public int TimeKey { get; set; }
public int FiscsalYear { get; set; }
public string LocationNum { get; set; }
public string Location { get; set; }
}
View:
#model List<FactWorkOrdersViewModel>
#{
ViewBag.Title = "Stored Procedure Test";
}
<div class="container">
<table class="table table-hover">
<thead>
<tr>
<th colspan="5"><h3>Stored Procedures results</h3></th>
</tr>
<tr>
<th>TimeKey</th>
<th>Fiscal Year</th>
<th>Location Number</th>
<th>Location</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#item.TimeKey
</td>
<td>
#item.WorkOrderAltKey
</td>
<td>
#item.FiscsalYear
</td>
<td>
#item.LocationNum
</td>
<td>
#item.Location
</td>
</tr>
}
</tbody>
</table>
<div>
Controller:
public IActionResult SPTest(ReportViewModel model)
{
DbConnection connection = db.Database.GetDbConnection();
using (DbCommand cmd = connection.CreateCommand())
{
cmd.CommandText = "ExecuteReport";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#ReportId", model.ID));
if (connection.State.Equals(ConnectionState.Closed))
{
connection.Open();
}
var result = cmd.ExecuteScalar();
//var result = cmd.ExecuteNonQuery();
if (connection.State.Equals(ConnectionState.Open))
{
connection.Close();
}
return View(result);
}
This is a possible duplicate.
Please refer to What is the difference between ExecuteScalar, ExecuteReader and ExecuteNonQuery? for more information.
Short answer : You need ExecuteReader not ExecuteScalar.
ExecuteScalar returns first column's value of first row. ExecuteReader will return the list of rows which we can iterate through and display on your page.
I figured it out, thanks #Amogh
public IActionResult SPTest(ReportViewModel model)
{
List<ViewModel> viewModel = new List<ViewModel>();
using (SqlConnection conn = new SqlConnection("server=ServerName;database=DBName; user id=user_id; password=password; MultipleActiveResultSets=true"))
{
conn.Open();
SqlCommand cmd = new SqlCommand("ExecuteReport", conn)
{
CommandType = CommandType.StoredProcedure
};
cmd.Parameters.Add(new SqlParameter("#ReportId", model.ID));
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
foreach (var item in rdr)
{
ViewModel vm = new ViewModel
{
TimeKey = (int)rdr.GetValue(0),
FiscsalYear = (int)rdr.GetValue(2),
LocationNum = (string)rdr.GetValue(5),
Location = (string)rdr.GetValue(6)
};
viewModel.Add(vm);
}
}
}
}
return View(viewModel);
}

ASP.NET MVC 4 data access

I am trying to show the employee details in a table. I created a model class EmployeeDetail, an EmployeeController and a view in EmployeeDetails.cshtml, plus a class for accessing the database.
EmployeeDetails is my model class:
[Serializable]
public class EmployeeDetails
{
private int _eid;
private string _ename;
private string _eaddress;
private string _gender;
private string _emobileno;
private bool _status;
private DateTime _ejoiningdate;
private DateTime _eleavedate;
#region ================= Code start for public variable =========================
[DataObjectField(true,true,false)]
public int eid {
get { return _eid; }
set { _eid = value; }
}
[DataObjectField(true, true, false)]
public string ename
{
get { return _ename; }
set { _ename = value; }
}
[DataObjectField(true, true, false)]
public string eaddress
{
get { return _eaddress; }
set { _eaddress = value; }
}
[DataObjectField(true, true, false)]
public string gender
{
get { return _gender; }
set { _gender = value; }
}
[DataObjectField(true, true, false)]
public string emobileno
{
get { return _emobileno; }
set { _emobileno = value; }
}
[DataObjectField(true, true, false)]
public bool status
{
get { return _status; }
set { _status = value; }
}
[DataObjectField(true, true, false)]
public DateTime ejoiningdate
{
get { return _ejoiningdate; }
set { _ejoiningdate = value; }
}
[DataObjectField(true, true, false)]
public DateTime eleavedate
{
get { return _eleavedate; }
set { _eleavedate = value; }
}
#endregion ==================== code end for public variable =================
}
Here is my EmployeeController:
public class EmployeeController : Controller
{
// GET: /Employee/
private Employeecon db = new Employeecon();
public ActionResult EmployeeDetails()
{
var studentList = new List<EmployeeDetails>{
new EmployeeDetails() { eid = 1, ename = "John", eaddress = "teszxs" } ,
new EmployeeDetails() { eid = 2, ename = "Steve", eaddress = "jfdsk" } ,
new EmployeeDetails() { eid = 3, ename = "Bill", eaddress = "jfdsk" } ,
new EmployeeDetails() { eid = 4, ename = "Ram" , eaddress = "jfdsk" } ,
new EmployeeDetails() { eid = 5, ename = "Ron" , eaddress = "jfdsk" } ,
new EmployeeDetails() { eid = 4, ename = "Chris" , eaddress = "jfdsk" } ,
new EmployeeDetails() { eid = 4, ename = "Rob" , eaddress = "jfdsk" }
};
return View();
}
}
I created EmployeeDetails.cshtml as a Razor view:
#model IEnumerable<Employee.Models.EmployeeDetails>
<html>
<head>
<title>Employee Details</title>
</head>
<body>
<div align="center">
<b> Employee Details</b>
</div>
<div align="right">
<p>
#Html.ActionLink("New Employee", "NewEmployee")
</p>
</div>
<table align="center" cellpadding="5" cellspacing="5" style="border:1px thin
black;" frame="box">
<tr>
<th>
Name
</th>
<th>
Address
</th>
<th>
Mobile no
</th>
<th>
Joining Date
</th>
</tr>
#foreach(var r in Model)
{
<tr>
<td>
#* #r.ename;*#
#Html.DisplayNameFor(m => r.ename); //but when I am declaring like that its showing error the call is ambiguous between the following methods or properties
</td>
</tr>
<tr>
<td>
#*#r.eaddress;*#
#Html.DisplayNameFor(m => r.eaddress);
</td>
</tr>
<tr>
<td>
#* #r.emobileno;*#
#Html.DisplayNameFor(m => r.emobileno);
</td>
</tr>
<tr>
<td>
#* #r.ejoiningdate;*#
#Html.DisplayNameFor(m => r.ejoiningdate);
</td>
</tr>
}
</table>
</body>
</html>
I am creating a separate folder for data access. I created a data context file Employeecon.cs:
public class Employeecon : DbContext
{
public Employeecon() : base("EmployeeContext")
{
}
public DbSet<EmployeeDetails> emp { get; set; }
}
And I added a connection string to the web.config file:
<add name="EmployeeContext"
connectionString="Data Source=LEVIOZA;Initial Catalog=Manali;Persist Security Info=True;User ID=sa;Password=pedcall"
providerName="System.Data.SqlClient" />
I want to connect to a SQL Server database, instead of local db, or I don't want to create database in the App_Data folder. Like we are did in the asp.net using SQL Server we pass the connection string using SqlConnection like that.
I am trying to connect but I don't know if it's working or not .
I don't know whats wrong with this program. I am trying to learn ASP.NET MVC and this is my first try. Please help me.
So you actually did a good job so far, let me point you to the rest.
Firstly, with database connection a side, you did created a simulation of data, which i assume you wonder why they did not shown in the view.
This is because you did not asked the controlled to use your data as model for the view. Yes, you did specify which type the model is, but you didn't supply it with data.
To fix it, pass the View() method the model instance you want, so it can bind it together.
return View(studentList);
Secondly, you want to extract those information from database, you only lacking querying the information you want from database and return it as model.
For example, lets create another url called /EmployeeDetailsFromDb
public ActionResult EmployeeDetailsFromDb()
{
var studentList = db.EmployeeDetails; // .EmployeeDetails should be changed to the table\dataset you want.
return View(studentList);
}
This will work, assuming the EmployeeDetails(if exists) is actually a collection of EmployeeDetails entities, which is what the view .cshtml expects.

How to display/store and retrieve image as varbinary(MAX) using ASP.NET MVC view

I am new to ASP.NET MVC, so kindly excuse for mistakes.
I need a view page (index.cshtml) where I can display the image, change/delete the image by storing it in Varbinary(max) column in a SQL Server table.
There are these columns in the database table:
ID int primary key Identity not null,
ImageName nvarchar(50) ,
ImagePicInBytes varbinary(MAX) null
I am using a Image.cs with this code:
public class Image
{
public int ID {get; set;}
public string ImageName {get; set;}
public byte[] ImagePicInBytes {get; set;}
}
ImageContext class as below
public class ImageContext : DbContext
{
public DbSet<Image> Images { get; set; }
}
Connection string as below
<connectionStrings>
<add name="ImageContext"
connectionString="server=.; database=Sample; integrated security =SSPI"
providerName="System.Data.SqlClient"/>
</connectionStrings>
ImageController as below
public class ImageController : Controller
{
private ImageContext db = new ImageContext();
// GET: /Image/
public ActionResult Index()
{
return View(db.Images.ToList());
}
// GET: /Image/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Image image = db.Images.Find(id);
if (image == null)
{
return HttpNotFound();
}
return View(image);
}
}
Have created views as below
public class ImageController : Controller
{
private ImageContext db = new ImageContext();
// GET: /Image/
public ActionResult Index()
{
return View(db.Images.ToList());
}
// GET: /Image/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Image image = db.Images.Find(id);
if (image == null)
{
return HttpNotFound();
}
return View(image);
}
// GET: /Image/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Image image = db.Images.Find(id);
if (image == null)
{
return HttpNotFound();
}
return View(image);
}
// POST: /Image/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Image image = db.Images.Find(id);
db.Images.Remove(image);
db.SaveChanges();
return RedirectToAction("Index");
}
}
}
My create.cshtml (view) as below
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.ImageName)
</th>
<th>
#Html.DisplayNameFor(model => model.ImagePicInBytes)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ImageName)
</td>
<td>
#Html.DisplayFor(modelItem => item.ImagePicInBytes)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Details", "Details", new { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
I have the below 3 questions
How can I create a new record in datatable by uploading new image from file system to Varbinary column in database?
How can I have the view to have FILEUPLOAD control in the 'create View' and 'Edit view'
Can I use HttpPostedFileBase to achieve the above from Create.cshtml? If yes: how? Any suggestions or reference links available?
first of all create a viewmodel for Image class
public class ImageViewModel
{
public string ImageName {get; set;}
public HttpPostedFileBase ImagePic {get; set;}
}
then for uploading a photo in your create view
#model ExmpleProject.Models.ImageViewModel
#using (Html.BeginForm("Create", "ControllerName", FormMethod.Post, new {enctype="multipart/form-data"})){
#Html.AntiForgeryToken()
#Html.LabelFor(m => m.ImageName)
#Html.TextBoxFor(m => m.ImageName)
#Html.LabelFor(m => m.ImagePic )
#Html.TextBoxFor(m => m.ImagePic , new { type = "file" })
<br />
<input type="submit" name="Submit" id="Submit" value="Upload" />
}
then in post method of your controller for create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ImageViewModel model)
{
if (ModelState.IsValid)
{
var uploadedFile = (model.ImagePic != null && model.ImagePic.ContentLength > 0) ? new byte[model.ImagePic.InputStream.Length] : null;
if (uploadedFile != null)
{
model.ImagePic.InputStream.Read(uploadedFile, 0, uploadedFile.Length);
}
Image image = new Image
{
ImageName = model.ImageName,
ImagePicInBytes = uploadedFile
}
db.Create(image);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
so for your edit method you can do similar implementation but instead of Create(image) use Update(image)

Many-to-many relationship read and write

I just want to get some clarity about link table for a many-to-many relationship in a ASP.NET MVC project. When the Controller and the Views are created, it seems like there are not any code for read and write to the link table!? The only thing that is autogenrated is the table OrderEmployee.
If I have understood it right, for each order I create, I also need to add the ID of the Employee who handled it in the OrderEmployee table? And when I want to list the Oders and want to know each Employee who handled that Order, I need to read from the OrderEmployee table? I can't find any tutorials about how to read and write to and from a link table.
Do I have to add this read and write code on my own in the controller? Preciate if I can get some clarity about this!
public class Order
{
public int ID { get; set; }
public string Name { get; set; }
public int? ManufacturerID { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public int EmployeeNumber { get; set; }
public virtual ICollection<Timeunit> Timeunits { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}
For reading and writing in a many to many relationship is not really difficult but hard to get it right in the beginning.
You don't have to add anything in your models, they are right.
Writing
I'll show you with an example of how to add a single order to an employee with a dropdown list. The concept for add multiple orders to employees is nearly the same, you'll find a link at the bottom with a tutorial.
First of all you should create view models like this :
public class CreateEmployeeViewModel
{
public int ID { get; set; }
public string Name { get; set; }
public int EmployeeNumber { get; set; }
public int SelectedOrderID { get; set; }
public SelectList OrdersList { get; set; }
}
Then in your EmployeesControler :
// GET: Employees/Create
public ActionResult Create()
{
/* Add this */
CreateEmployeeViewModel model = new CreateEmployeeViewModel();
model.OrdersList = new SelectList(db.Orders.ToList(), "ID", "Name");
return View(model);
}
The first parameter will be the list of objects in which you want to select something (an Order in this case). The second parameter is the name of the propertie of your Order you want to pass to the view model (as SelectOrderID) and finally the third parameter is the value you want to display in the dropdownlist.
And in your Create.cshtml replace the first line with this :
#model TestStackOverflow.Models.CreateEmployeeViewModel
Next add the dropdown list in the Html.BeginForm :
<div class="form-group">
#Html.LabelFor(model => model.OrdersList, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.SelectedOrderID, Model.OrdersList, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.SelectedOrderID, "", new { #class = "text-danger" })
</div>
</div>
Now you should have this in the create view.
Then go back to your EmployeesControler and find the POST method for create and replace it with this :
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateEmployeeViewModel model)
{
if (ModelState.IsValid)
{
Employee employee = new Employee()
{
Name = model.Name,
ID = model.ID,
EmployeeNumber = model.EmployeeNumber,
Orders = new List<Order>()
};
employee.Orders.Add(db.Orders.Where(x => x.ID == model.SelectedOrderID).FirstOrDefault());
db.Employees.Add(employee);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
It will create a new Employee based on the view model values and add an order to this Employee. Now if you check your OrderEmployees table you should see that a new entry is created when you're adding an Employee.
Reading
Reading the values is really simpler than writing.
If you want to read all the employees that are handling an order, just do it like this (I took Index.cshtml from the Orders to demonstrate it)
Add this at the top of your file:
#using YourNameSpace.Models
And now a little further modify the file. It should look like this:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.ManufacturerID)
</td>
<td>
#foreach (Employee e in item.Employees)
{
#e.Name <br />
}
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Details", "Details", new { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
Here you can find a tutorial on how to use SelectList to handle one to many relationships and many to many relationships in your views.
Hope this answer will help you.

Resources