How to Display multiple images from db using MVC3 - asp.net

I am new to MVC.I have saved the image and some data but can't display the saved images. I want to display all saved images in the main page.
Model: Get the db list from model
public List<Products> GenreList()
{
}
Controller
public ActionResult MYsample()
{
var MyList = storeDB.GenreList();
var a= MyList.Count;
if (a != null)
{
foreach (var li in MyList)
{
return File(li.fileContent, li.mimeType,li.fileName);
}
}
return View(MyList);
}
View
#foreach (var item in Model)
{
<img src="#Url.Action("MYsample", "HomeController", new { id = item.ProductID })" alt="#item.Productname" />
}

You could start by writing a controller action that will serve the images to the response stream:
public ActionResult Image(int id)
{
// you should add a method to your repository that returns the image
// record from the id
Products image = storeDB.Get(id);
return File(image.fileContent, image.mimeType);
}
and then in your main controller action send the list of images to the view:
public ActionResult MySample()
{
var model = storeDB.GenreList();
return View(model);
}
and then in your strongly typed view loop through the images and generate an <img> tag for each image by pointing its src property to the newly created controller action:
#model MyList
#foreach (var li in MyList)
{
<img src="#Url.Action("Image", new { id = li.Id })" alt="" />
}
If you don't want to have a separate controller action that will query the database and retrieve the image record from an id you could use the data URI scheme. Bear in mind though that this is not supported by all browsers.
So the idea is that your controller action will send the image data to the view:
public ActionResult MySample()
{
var model = storeDB.GenreList();
return View(model);
}
and then inside your strongly typed view you could loop through the list and generate the proper <img> tag:
#model MyList
#foreach (var li in MyList)
{
<img src="src="data:#(li.mimeType);base64,#(Html.Raw(Convert.ToBase64String(li.fileContent)))" alt="" />
}

Related

Having a difficulty passing value of objects in view asp.net MVC

I have joined two tables(Projects, Task_Distribution) and pass the values to View as viewbag. But I can't access the value in view(such as: #item.Project_Id) and if I write like #item it displays the result like This image
How can I access only the value?
here is my controller code:
public class TableController : Controller
{
// GET: Table
public ActionResult Table()
{
Database_testEntities1 db1 = new Database_testEntities1();
List<Project> p = new List<Project>();
List<Task_Distribution> t = new List<Task_Distribution>();
var query = (from PI in db1.Projects join TI in
db1.Task_Distribution on PI.Project_Id equals TI.Project_Id select new { PI.Project_Id, TI.Employee_Id }).ToList();
ViewBag.table = query;
return View();
}
}
And this is my view
#{
ViewBag.Title = "Table";
}
<h2>Table</h2>
<table>
#foreach (var item in ViewBag.table)
{
<tr>
<td>
#item
</td>
</tr>
}
</table>
Can you guys give me a solution, please?
See this part of your LINQ expression,
select new { PI.Project_Id, TI.Employee_Id }
You are projecting the result to an anonymous object. So what you have in the ViewBag is a list of these anonymous objects. When you loop through them and executes the code #item, razor will call the ToString method on that which renders the property name and values(which is what you are seeing)
You can create a view model to represent this data and do a projection using that
public class ProjectEmployeeVm
{
public int ProjectId { set;get;}
public int EmployeeId { set;get;}
}
Now in your LINQ expression,
select new ProjectEmployeeVm { ProjectId = PI.Project_Id,EmployeeId = TI.Employee_Id }
Now in your view,you can use cast your viewbag item to a list of this view model
#foreach (var item in ViewBag.table as List<ProjectEmployeeVm>)
{
<p>#item.ProjectId<p>
<p>#item.EmployeeId <p>
}
Also now since you have a view model, why not use that to transfer data to view instead of using dynamic view bag which is prone to errors.
var items = (from PI in db1.Projects join TI in
db1.Task_Distribution on PI.Project_Id equals TI.Project_Id
select new ProjectEmployeeVm { ProjectId = PI.Project_Id,
EmployeeId = TI.Employee_Id
}).ToList();
return View(items);
Now in your view,
#model List<ProjectEmployeeVm>
#foreach (var item in Model)
{
<p>#item.ProjectId<p>
<p>#item.EmployeeId <p>
}

how can i save more than one image in the database?

I just want to save the route of the images in the database.
So i try this.
And i get this error System.NullReferenceException: Object reference not set to an instance of an object.
This is my Controller
public ActionResult SaveImages(IEnumerable<HttpPostedFileBase> img, Imagenes images)
{
foreach (var n in img)
{
var PhotoUrl = Server.MapPath("/images" + n.FileName);
if (n != null && n.ContentLength > 0)
n.SaveAs(PhotoUrl);
images.imgUrl = "/images" + n.FileName;
db.Imagenes.Add(images);
db.SaveChanges();
}
return View("Index");
}
This is my model class
public partial class Imagenes
{
public int id { get; set; }
[StringLength(200)]
public string imgUrl { get; set; }
}
my View
#{
ViewBag.Title = "Home Page";}
#using (Html.BeginForm("SaveImages", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
<input type="file" name="img" id="img" multiple />
<input type="submit" name="submit" value="Save"/>
</div>}
The error you are getting is nothing about the image saving part, but I'm assuming it's the use of your images property...
As you didn't specify where that property comes from, MVC automatically assumes that's a POST Variable, and in your HTML, you have nothing of sorts...
change your action code to:
public ActionResult SaveImages(IEnumerable<HttpPostedFileBase> img)
{
const string folderToUpload = "/images";
foreach (var n in img)
{
var imageToUpload = folderToUpload + n.FileName;
var photoUrl = Server.MapPath(imageToUpload);
if (n != null && n.ContentLength > 0) {
n.SaveAs(photoUrl); // save to folder
var images = new Imagenes {
imgUrl = imageToUpload
};
db.Imagenes.Add(images); // add to repository
db.SaveChanges(); // save repositorychanges
}
}
return redirectToAction("Index");
}
I'm also assuming that db was already injected in your constructor, and it's not NULL
Code edited:
create a constant variable to have the folder to upload, so you don't repeat that code over and over
create a variable to hold the full path of the image, so you don't repeat that code over and over (remember: DRY - Don't Repeat Yourself)
save to database only if the file was saved
create a new variable to hold your object to be saved
redirect to the action using redirectToAction as you might have some calls in your Index and only redirecting to the View would give you an error
to be persistence, change the PhotoUrl to photoUrl (local variables = start with lowercase)

Paging on Partial View

I have a main view with a partial view.
The partial view allows paging, I am using Bootstrap.
Controller:
public ActionResult Main()
{
return View();
}
//[ChildActionOnly]
public ActionResult _Partial(int page)
{
Model = //returns records for requested page
return View(Model);
}
View:
<ul class="pagination">
#for (int i = 1; i <= model.TotalPages; i++)
{
<li>#Html.ActionLink(i.ToString(), "_Partial", new { page = i, })</li> }
}
</ul>
My problem is, although the paging works, selecting a page is calling the _Partial Action directly ( after I removed [ChildActionOnly]
So on paging it loads the Partial View only without the Main View which it forms part of...therefor it is missing the 'frame' provided by the Main View or any formatting.
Should I be following a different approach or is there a way to call a Partial Action and it’s Main Action?
I guess I would have liked to do something like…
<li>#Html.ActionLink(i.ToString(), "Main + _Partial", new { page = i, })</li>
Or how can I get Bootstrap Paging (I don't want to go the Ajax route) to work on a Partial View?
If you don't want to use ajax, then you have to return the whole page. Here an example for your case:
Controller:
public ActionResult Main()
{
return View();
}
public ActionResult SomeAction(int page) //Name this as your like
{
// I use viewbag here for convenience,
//you should consider to create new view model if necessary.
ViewBag.PageNum = page;
return View();
}
//[ChildActionOnly]
public ActionResult _Partial(int page)
{
Model = //returns records for requested page
return View(Model);
}
View "SomeAction.cshtml":
#*Put your Main page content here*#
#Html.Action("SomeAction", "YourControllerName", new { page = ViewBag.PageNum })
#*Put your Main page content here*#
And Your pagination should change to:
<ul class="pagination">
#for (int i = 1; i <= model.TotalPages; i++)
{
<li>#Html.ActionLink(i.ToString(), "SomeAction", new { page = i, })</li> }
}
</ul>
Keep in mind that I created the "SomeAction" only because I don't know what exactly does your "Main" action do. If the "Main" is simply the 1st page, then you should merge the "SomeAction" and "Main" into one:
public ActionResult Main(int page = 1)
{
ViewBag.PageNum = page;
return View();
}

Display uploaded images

I'm trying to create a simple image gallery. Uploading works, but I have problems with displaying those images.
In the internet I found that this is the right way to do it:
[NotMapped]
public string ImageUrl
{
get
{
var isEmpty = String.IsNullOrWhiteSpace(ImgName);
if(isEmpty)
{
return Path.Combine("~/Images", "noImageAvailable.png");
}else
{
return Path.Combine("~/Images/uploaded", ImgName);
}
}
}
and in the view
#foreach (var item in Model) {
...
#{ var imgPath = HostingEnvironment.MapPath(item.ImageUrl); }
<img src="#Url.Content(imgPath)"/>
Which produces:
<img src="C:\......\Images\uploaded\0_634927659072110613.jpg"/>
What worked for me is:
[NotMapped]
public string ImageUrl
{
get
{
var isEmpty = String.IsNullOrWhiteSpace(ImgName);
if(isEmpty)
{
return Path.Combine("../Images", "noImageAvailable.png");
}else
{
return Path.Combine("../Images/uploaded", ImgName);
}
}
}
and in the view:
#foreach (var item in Model) {
.....
<img src="#Url.Content(item.ImageUrl)"/>
Which produces:
<img src="../Images/uploaded\0_634927649098750170.jpg"/>
Remarks
There are 2 differences:
~/Images vs ../Images
the lines in the view
What is interesting is that the line
<img src="C:\......\Images\uploaded\0_634927659072110613.jpg"/>
displays an image in a static standalone file, while when it's served by the IIS it doesn't. There is just blank space instead of an image.
My question is what is the right approach, and also why does't the first one work?
Your code is doing exactly what you're asking. The 1st one doesn't work because var imgPath = HostingEnvironment.MapPath(item.ImageUrl); returns a physical path on the server to the image URL, NOT a URL. Use the 1st block with <img src="#Url.Content(item.ImageUrl)"/>. This looks like:
[NotMapped]
public string ImageUrl
{
get
{
var isEmpty = String.IsNullOrWhiteSpace(ImgName);
if(isEmpty)
{
return Path.Combine("~/Images", "noImageAvailable.png");
}else
{
return Path.Combine("~/Images/uploaded", ImgName);
}
}
}
with your view:
#foreach (var item in Model) {
.....
<img src="#Url.Content(item.ImageUrl)"/>
"~/Images/..." in .net says from web root, find the folder Images,
then ...
"../Images/..." is relative to the current location - go up
one folder, find folder images, then ...

mvc3 partial view error

I want to make a form for entering customer data. It consists of several text boxes and a combobox. And it is the whole problem lies in this combobox. When I trying to render this partialview , gets error: "Object reference not set to an instance of an object."
This is partialview controller code
public PartialViewResult GetStates()
{
var states = from s in conn.order_data select s.state;
return PartialView(states.ToList());
}
GetStates partialview
#model IEnumerable<bookstore.state>
#foreach (var item in Model) {
<select>
<option>#item.STATE_Name</option>
</select>
}
part of main view
<div class="editor-field">
#{Html.RenderPartial("GetStates");}
</div>
Please, help
Unless you are loading the view dynamically (in which case you could do it with jquery get)
here is how you could do it
Controller:
public ActionMethod MainView()
{
var model = new myMainModel { States = from s in conn.order_data select s.state };
return View()
}
Main View:
#Html.Partial("MyPartialViewName", Model.States);
Try this:
if(states != null)
{
return PartialView(states.ToList());
}
return PartialView();

Resources