Error loading images from database - asp.net

I have a question about showing images loaded from a mysql database in an Index view.
In my database table "deliverables" I have "item_id", "deliverable_image" and "afstudeerrichting_id". "item_id" and "afstudeerrichting_id" are FK from other tables.
I want to show the images when afstudeerrichting_id = ..
Controller:
public ActionResult Index()
{
var model = repository.GetIdsOfImages(1);
return View(model.ToList());
}
public ActionResult ShowImage(int id)
{
IQueryable<byte[]> data = repository.GetImages(id);
byte[] firstimage = data.First();
return File(firstimage, "image/png");
}
Repository:
public IQueryable<long> GetIdsOfImages(int afstudeerrichtingid)
{
return from deliverable in entities.deliverables
where deliverable.afstudeerichting_id.Equals(afstudeerrichtingid)
select deliverable.item_id;
}
public IQueryable<byte[]> GetImages(int itemID)
{
return from deliverable in entities.deliverables
where deliverable.item_id.Equals(itemID)
select deliverable.deliverable_image;
}
View:
#foreach(var imgID in Model.DeliverablesIDsList)
{
<img src="#Url.Action("ShowImage", "Deliverable", new { DeliverableID = imgID })" />
}
In my Viewmodel I have:
public List<long> DeliverablesIDsList { get; set; }
public int DeliverableID { get; set; }
But now I always get this error:
he model item passed into the dictionary is of type 'System.Collections.Generic.List`1[System.Int64]', but this dictionary requires a model item of type 'GDMfrontEnd.Models.DeliverableViewModel'.
Does someone knows what I'm doing wrong?

you're sending to the view a list of int64 repository.GetIdsOfImages(1).ToList() and the view requires a DeliverableViewModel, so you must create a model and put the list into the model and send it to the view
the action should looks like:
public ActionResult Index()
{
var model = repository.GetIdsOfImages(1);
DeliverableViewModel model = new DeliverableViewModel()
model.DeliverablesIDsList = repository.GetIdsOfImages(1).ToList();
return View(model); //send to the view a model type of DeliverableViewModel
}
now with ActionResult ShowImage, the action expect id parmeter and you're sending DeliverableID, so change de var name
public ActionResult ShowImage(int DeliverableID)
{
IQueryable<byte[]> data = repository.GetImages(DeliverableID);
byte[] firstimage = data.First();
return File(firstimage, "image/png");
}

Related

Asp.Net Core: How to json serialize and deserialize IFormCollection?

In a controller I serialized form data to json and saved to database:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(IFormCollection formData)
{
var json = JsonConvert.SerializeObject(formData);
var doc = new Doc()
{
Subject = formData["subject"],
Content = json
};
_context.Docs.Add(doc);
_context.SaveChanges();
return RedirectToAction("Edit", new { Id = doc.Id });
}
Now, I'd like to deserialize form data and reconstruct the form:
public IActionResult Edit(int id)
{
var doc = _context.Docs
.Where(o => o.Id == id).FirstOrDefault();
if (doc == null)
{
ViewData["ErrorMessage"] = "Not found";
return View("Error");
}
var formData = JsonConvert.DeserializeObject<IFormCollection>(doc.Content);
ViewData["FormData"] = formData;
return View(doc);
}
The above will throw an exception at deserialization:
JsonSerializationException: Cannot create and populate list type Microsoft.AspNetCore.Http.IFormCollection. Path '', line 1, position 1.
If I do not specify type, then deserialization succeeds; but I prefer it
to be deserialized to IFormCollection. What is the proper way to deserialize IFormCollection?
Also, the reason I'm saving json is because, I'm dealing with 30 or so types of forms, and I do not want to create strongly typed model objects for each of them. Any advice is welcome.
The way I used to deal with json object in Database:
In your entity object add an other class to handle mapping with your json object :
public class Contact
{
public int Id { get; set; }
internal string _Data { get; set; }
[NotMapped]
public UserData Data
{
get { return _Data == null ? null : JsonConvert.DeserializeObject<UserData>(_Data); }
set { _Data = JsonConvert.SerializeObject(value); }
}
}
public class UserData
{
public string Name { get; set; }
//Add your json data here
}
And my controller look like
public IActionResult Add(AddContactViewModel model)
{
var contact = new Contact()
{
Data = JsonConvert.DeserializeObject<UserData>(model.Data.ToString())
};
_contactService.Add(contact);
return new OkObjectResult(contact);
}
public class AddContactViewModel
{
public JObject Data { get; set; }
}
Thank's to mapping, when you access the object data contained by the object contact you can access all your data préviously defined in the UserData object (Object names can change in your case)
var contact = new Contact()
{
Data = JsonConvert.DeserializeObject<UserData>(model.Data.ToString())
};
contact.Data.Name;

Unusual behavior DropDownList MVC 5

I managed to populate DropDownList with value from a Database in ASP.NET MVC 5. My goal is to assing one of the dropDownList's value to a specific model, and send it back to the Database. So, if i leave the default value in the dropdownlist, the data in SQL server is null, which is Okay, but if I choose an option, I get an error :
Exception thrown: 'System.InvalidOperationException' in System.Web.Mvc.dll ("There is no ViewData item of type 'IEnumerable' that has the key 'Status'."). I tried everything so far and i am opened for suggestions. Thank you !!!
In Controller :
ViewBag.Status = new SelectList(db.Status, "Id", "Name");
in View
#Html.DropDownList("Status","Select status...")
In Controller so far..
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult Apply(ViewModelVM vm,int x=0)
{
myDb db = new myDb();
ViewBag.SocialStatus = new SelectList(db.SocialStatuses, "Id", "StatusDescription");
return View();
}
[HttpPost]
public ActionResult Apply(ViewModelVM vm)
{
if (ModelState.IsValid)
{
using (myDb db = new myDb())
{
var personalinfo = new PersonalInformation()
{
FirstName = vm.PersonalInformation.FirstName,
LastName = vm.PersonalInformation.LastName,
Birthdate = vm.PersonalInformation.Birthdate,
SocialStatus = vm.SocialStatus
};
ViewBag.SocialStatus = new SelectList(db.SocialStatuses, "Id", "StatusDescription");
db.PersonalInformations.Add(personalinfo);
db.SaveChanges();
}
return View("Success");
}
return View();
}
The model:
public partial class Status
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public SocialStatus()
{
PersonalInformations = new HashSet<PersonalInformation>();
}
public int Id { get; set; }
[StringLength(20)]
public string StatusDescription { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<PersonalInformation> PersonalInformations { get; set; }
}
}
The ViewModel:
public class ViewModelVM
{
...
public Status SocialStatus { set; get; }
...
}
Firstly your using a view model so include a property in your view model for the SelectList
public IEnumerable<SelectListItem> StatusList { get; set; }
Next remove the parameter for the model from the GET method (and since you don't appear to be using the value of x, that should be removed also)
[HttpGet]
public ActionResult Apply(ViewModelVM vm,int x=0)
{
myDb db = new myDb();
ViewModelVM model = new ViewModelVM()
{
StatusList = new SelectList(db.SocialStatuses, "Id", "StatusDescription");
};
return View(model); // return the model to the view
}
Next, your dropdown is binding to a property named Status but your view model does not contain a property named status (its SocialStatus) and SocialStatus is a complex object and you cannot bind a <select> to a complex object (a <select> only posts back a single value (or array or values in the case of <select multiple>).
In addition, because your view model contains a property which is a complex object with validation attributes on its properties, ModelState will always be invalid because you do not post back a value for StatusDescription. As a result you always return the view in the POST method, and because you have not reassigned ViewBag.Status = ...., it is null, hence the error.
Remove property public Status SocialStatus { set; get; } and include
[Display(Name = "Social Status")]
[Required(ErrorMessage = "Please select a status")]
public int SocialStatus { get; set; }
an then in the view, strongly bind to your model using
#Html.LabelFor(m => m.SocialStatus)
#Html.DropDownListFor(m => m.SocialStatus, Model.StatusList, "-Please select-")
#Html.ValidationMessageFor(m => m.SocialStatus)
Then, in the POST method, if ModelState is invalid, populate the select list again before returning the view
if(!ModelState.IsValid)
{
model.StatusList = new SelectList(db.SocialStatuses, "Id", "StatusDescription");
return View(model);
}
// save and redirect
Finally, review What is ViewModel in MVC?.

How to keep the values filled in a form and recover after navigating to another controller

I am facing this situation. I have a form that I filled with three values. Then by clicking on a button I'm in another controller and I create an XmlDocument object I recovered via TempData. Once completed action coming back to my form naturally when all data has disappeared. My question is, how do I fill out the form, keep these values, and once the XML created to fill my database with the form data and XML created.
Layout controller
public class LayoutController : Controller
{
[HttpGet]
public ActionResult Create()
{
var Layout = new LayoutModel();
return View(Layout);
}
[HttpPost]
public ActionResult Create(LayoutModel Layout)
{
if (Layout == null)
{
return Content("le LayoutModel est nul");
}
else
{
TempData["DocName"] = Layout.Nom;
if (TempData["xmlAssociated"] != null)
{
Layout.xmlAssociated = (string)TempData["xmlAssociated"];
ManageXML.Models.COracleConn.GetInstance().InsertLayout(Layout);
}
else
{
return Content("On a pas recuperé l'XML");
}
return RedirectToAction("ListOfTopsAndMarges", "Entete_Marge");
}
}
}
XMLRecord controller
public class XMLRecordController : Controller
{
[HttpGet]
public ActionResult HandleForm()
{
var file = new XMLRecord()
{
Records = new List<XMLRecord>(){ new XMLRecord(){ Type="", Contenu="" }}
};
return View(file);
}
[HttpPost]
public ActionResult HandleForm(XMLRecord file)
{
if (file == null)
{
return HttpNotFound();
}
else
{
file.DocName = (string)TempData["DocName"];
string recup = file.GenerateXML(file);
TempData["xmlAssociated"] = recup;
return RedirectToAction("Create", "Layout");
}
}
}
public class LayoutModel
{
public string Nom { get; set; }
public string Type { get; set; }
public string Contenu { get; set; }
public string xmlAssociated {get; set;}
}
I want to retain my Type, my Contenu and my Nom properties even if I am going to another controller
Thnak for your help #Heymega

How to bind bropdown list in Razor View (If view is not bound with any model)

Can anybody suggest me how bind a dropdown list in MVC Razor view. I am using MVC 4. I have a view that is not bound with any model class.
public class Util {
public List<EmployeeType> GetEmpTypes() {
return (new List<EmployeeType>(){
new EmployeeType(){ID=101, Text="Permanent"},
new EmployeeType(){ ID=102, Text="Temporary"}
});
}
}
public class EmployeeType {
public int ID { get; set; }
public string Text { get; set; }
}
I have this sample code. I am new to MVC Now after this I don't know how to bind the collection returned by GetEmployeeTypes() Method to a dropdown list
Your class with method
public class Util {
public List<EmployeeType> GetEmpTypes() {
return (new List<EmployeeType>(){
new EmployeeType(){ID=101, Text="Permanent"},
new EmployeeType(){ ID=102, Text="Temporary"}
});
}
}
Your model class with properties
public class EmployeeType {
public int ID { get; set; }
public string Text { get; set; }
}
This is sample action
public ActionResult ViewName()
{
Util xxx=new Util();
List<SelectList> SelectedItems =new List<SelectList>();
List<EmployeeType> items =xxx.GetEmpTypes();
foreach (var t in items )
{
SelectListItem s = new SelectListItem();
s.Text = t.Text;
s.Value = t.ID;
SelectedItems.Add(s);
}
ViewBag.xxxxx= SelectedItems;
return view();
}
In View
#Html.DropDownList("xxxxx", new SelectList(ViewBag.xxxxx, "Text", "Value"))
This above code just like a key, i don't tested for that code ran successfully. you can get some idea for how to bind dropdown from my code.
I had a Class like this to get all EmployeeTypes
public class Util
{
public List<EmployeeType> GetEmpTypes()
{
return (new List<EmployeeType>(){
new EmployeeType(){ID=101, Text="Permanent"},
new EmployeeType(){ ID=102, Text="Temporary"}
});
}
}
public class EmployeeType
{
public int ID { get; set; }
public string Text { get; set; }
}
In Controller I have written code to get the List of Employee Types
Util obj = new Util();
var v = obj.GetEmpTypes();
ViewBag.EmployeeTypes = v;
return View();
In the View I have written code to bind dropdown.
#Html.DropDownList("EmployeeTypes",new SelectList(ViewBag.EmployeeTypes,"ID","Text"));
Thanks #Ramesh Rajendran ( Now I understood the concept to bind dropdown)
*strong text*you should create the model selectlist like here:
public static List<EmployeeType> GetEmpTypes() {
return (new List<EmployeeType>(){
new EmployeeType(){ID=101, Text="Permanent"},
new EmployeeType(){ ID=102, Text="Temporary"}
});
}
public static SelectList GetMyEmpTypes
{
get { return new SelectList(GetEmpTypes(), "ID", "Text"); }
}
then you access this method in dropdown list like
#Html.DropDownList("Name",yourProjectNameSpace.Util.GetMyEmpTypes())
when you will submit your form then it value bidden with Name get post to controller.
it is not necessary to bind with model class.you can receive the value on controller with the name that you have given in view like:
#Html.DropDownList("Name",yourProjectNameSpace.YourClass.GetEmpTypes())
Now you can recive the name value at controller like:
public ActionResult test(String Name)
{
return view();
}
and make your method static i.e GetEmpTypes() so that you can access it from view.

Show images from IQueryable in View

I have a question about showing images loaded from a mysql database in a view.
In my database table "deliverables" I have "item_id", "deliverable_image" and "afstudeerrichting_id". "item_id" and "afstudeerrichting_id" are FK from other tables.
I want to show the images when afstudeerrichting_id = ..
Controller:
public ActionResult Index()
{
var model = repository.GetIdsOfImages(1);
return View(model.ToList());
}
public ActionResult ShowImage(int afstudeerrichtingid)
{
IQueryable<byte[]> data = repository.GetImages(afstudeerrichtingid);
var thedata = data.First();
return File(thedata, "image/png");
}
Repository (where I get the images):
public IQueryable<long> GetIdsOfImages(int afstudeerrichtingid)
{
return from deliverable in entities.deliverables
where deliverable.afstudeerichting_id.Equals(afstudeerrichtingid)
select deliverable.item_id;
}
public IQueryable<byte[]> GetImages(int afstudeerrichtingid)
{
return from deliverable in entities.deliverables
where deliverable.afstudeerichting_id.Equals(afstudeerrichtingid)
select deliverable.deliverable_image;
}
View:
#foreach(var imgID in Model.DeliverablesIDsList)
{
<img src="#Url.Action("ShowImage", "Deliverable", new { DeliverableID = imgID })" />
}
In my Viewmodel:
public List<long> DeliverablesIDsList { get; set; }
public int DeliverableID { get; set; }
Now I get the error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[System.Int64]', but this dictionary requires a model item of type 'GDMfrontEnd.Models.DeliverableViewModel'.
What should I change in my ViewModel? Or what am I doing wrong?
You can do that:
1) pass to the view a list of images' ids, and build list like this
#foreach(var imgId in model.ImgIdsList)
{
<img src="#Url.Action("ShowImage", "Deliverable", new { imageId = imgId })" />
}
2) in controller, which open this view, simply build a ImgIdsList (probably you need a GetIdsOfImagesWithAfstudeerichtingid(int afstudeerrichtingid), which would return a list of int)
3) you should your ShowImage method - not pass afstudeerrichtingid, but unique id of image; of course in this method you should method like GetImageById(int id).

Resources