I'm relatively new to ASP.net mvc, and am experiencing a very strange browser error. The problem is that it's on the customer's pc (which I have yet to get access to).
There seems to be an intermittent problem posting data from his computer, at the moment he has only tried chrome (and I have requested he try different browsers). I haven't been able to replicate the issue and have tried on two computers, three browsers and three different operating systems (windows 7, windows 8 (via mac parallels) and Osx Mavericks) .
I'll post the model and relevant controller code (hopefully it's not too sloppy coding)
I've clarified the following:
- we are both using the same version of chrome
- we both use the same ISP
- He has AVG running
-the site is hosted on Azure
- there is plenty of database and file memory allocated (only 10% being used)
- very little in my code has varied from online examples and again, it all works for me
So my question is really, where else do I look to find the errors:
- is there something in the code that I should consider adding or changing
- could it be a cookie issue on his version of chrome?
- is there a firewall issue somewhere?
model
public class KitchenItem:Post
{
public virtual ICollection<Image> Images { get; set; }
//Optional Project Variables
public bool Project { get; set; }
public string ProjectName { get; set; }
public string Customer { get; set; }
public DateTime? projectStart { get; set; }
public DateTime? projectEnd { get; set; }
}
}
inherited model:
public class Post
{
public int Id
{ get; set; }
[Required]
public string Title
{ get; set; }
[Required]
[Display(Name="Short Description")]
[DataType(DataType.MultilineText )]
public string ShortDescription
{ get; set; }
[Required]
[AllowHtml]
[UIHint("tinymce_full_compressed")]
public string Description
{ get; set; }
[Display(Name = "Meta Keywords")]
[DefaultValue (" ")]
public string Meta
{ get; set; }
public string UrlSlug
{ get; set; }
public bool Published
{ get; set; }
public DateTime? PostedOn
{ get; set; }
public DateTime? Modified
{ get; set; }
public int? CategoryID { get; set; }
public Category Category
{ get; set; }
[NotMapped]
public HttpPostedFileBase uploadedFile { get; set; }
public string mainImagePath { get; set; }
public virtual ICollection<Tag> Tags
{ get; set; }
}
ViewModel:
public class CreateProjectViewModel
{
public KitchenItem KitchenItem { get; set; }
[Display(Name = "Upload Image")]
public HttpPostedFileBase[] ImagesFiles { get; set; }
public Image[] Images { get; set; }
public int CategoryID { get; set; }
public int[] imageDeletes { get; set; }
}
Create Post:
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateProjectViewModel viewModel)
{
KitchenItem model = new KitchenItem();
model = viewModel.KitchenItem;
try
{
/*
*Create ID from total Images to allow for specific folders to be created when file saved, iteration (totalImages)
*Calls for loop for each element of array to ensure that specific titles and tags are associated to correct image
* Add image to model collection to be saved to db
*/
List<Image> imgCollection = new List<Image>();
int totalKitchenItems = unitofWork.KitchenItemRepository.dbSet.Count() + 1;
//update model images
model.Images = handleEditImage(viewModel.ImagesFiles, viewModel.Images, imgCollection, model.Id);
//Log date posted
model.PostedOn = DateTime.Now;
Category cat = new Category();
model.Category = unitofWork.CategoryRepository.GetByID(viewModel.CategoryID);
//create post
unitofWork.KitchenItemRepository.Insert(model);
unitofWork.Save();
return RedirectToAction("Index");
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}",
validationErrors.Entry.Entity.GetType().FullName,
validationError.PropertyName,
validationError.ErrorMessage);
}
foreach (var eve in dbEx.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
}
PopulateCategoriesDropDownList(0);
return RedirectToAction("Index");
}
}
Handle Image & Add Image Functions:
public ICollection<Image> handleEditImage(HttpPostedFileBase[] imageFiles, Image[] images, ICollection<Image> modelImages, int modelID)
{
/*
*Create ID from total Images to allow for specific folders to be created when file saved, iteration (totalImages)
*Calls for loop for each element of array to ensure that specific titles and tags are associated to correct image
* Add image to model collection to be saved to db
*/
List<Image> imgCollection = new List<Image>();
for (int i = 0; i < 5; i++)
{
Image uploadImage = new Image();
//check to make sure there is an image
if (imageFiles[i] != null)
{
//handle httppostedfilebase conversion to image file and add Url to image model
uploadImage = AddImage(imageFiles[i], images[i], modelID);
//Add img to be updated to model
imgCollection.Add(uploadImage);
}
}
if (modelImages != null)
{
//check for deleted images
foreach (var img in modelImages)
{
//loop through image array to determine whether image is currently assigned to model
for (int i = 0; i < 5; i++)
{
if (images[i].ImageUrl != null)
{
//replace string element modified before passed to view
images[i].ImageUrl = images[i].ImageUrl.Replace("../../", "~/");
}
if (img.ImageUrl == images[i].ImageUrl)
{
imgCollection.Add(img);
}
}
}
}
return imgCollection;
}
public Image AddImage(HttpPostedFileBase imageToSave, Image modelImage, int Id)
{
Image img = new Image();
img = modelImage;
img.ImageUrl = SaveUploadedFile(imageToSave, Id);
unitofWork.ImagesRepository.Insert(img);
return img;
}
Related
I need help with Entity Framework.
Controller:
public ActionResult Create([Bind(Prefix = "visit")] visit visit, [Bind(Prefix = "drugsEdition")] IEnumerable<drugsEdition> drugsEdition, [Bind(Prefix = "accessoryEdition")] IEnumerable<accessoryEdition> accessoryEdition, [Bind(Prefix = "servicesEdition")] IEnumerable<servicesEdition> servicesEdition)
{
Models.VisitDetails visitDetails = new Models.VisitDetails();
visitDetails.visit = visit;
if (ModelState.IsValid)
{
db.visit.Add(visit);
if (drugsEdition != null)
{
foreach (var item in drugsEdition)
{
item.idVisit = visit.id;
db.drugsEdition.Add(item);
}
}
if (accessoryEdition != null)
{
foreach (var item in accessoryEdition)
{
item.idVisit = visit.id;
db.accessoryEdition.Add(item);
}
}
if (servicesEdition != null)
{
foreach (var item in servicesEdition)
{
item.idVisit = visit.id;
db.servicesEdition.Add(item);
}
}
db.SaveChanges();
return RedirectToAction("Details", new { id = visit.id });
}
return View(visitDetails);
}
Model:
[Table("servicesEdition")]
public partial class servicesEdition
{
public int id { get; set; }
public int idService { get; set; }
public int idVisit { get; set; }
public double priceSell { get; set; }
[ForeignKey("idService")]
public virtual services services { get; set; }
}
In this code, I added a new visit to the database, and I want get the visit's id after the code line db.visit.Add (visit). When I add new drugsEdition and new accessoryEdition, this code is correct and added good idVisit, but when I addedservicesEdition idVisit = 0. Why 'servicesEdition' doesn't get good idVisit ?
If you add a virtual navigational property of type Visit, EF will get the corresponding visit id and fill that in when it saves a servicesEdition object on your SaveChanges method call.
I would also renaming the foreign key property to VisitId so that the referential integrity works by convention (naming convention) and you do not need to explicitly use the ForeignKey attribute. I would also recommend you to use PascalCasing when writing C# classes( not necessarily needed for your code to work)
public partial class ServicesEdition
{
public int id { get; set; }
public int idService { get; set; }
public int VisitId { get; set; }
public virtual Visit Visit { get; set; }
public double priceSell { get; set; }
[ForeignKey("idService")]
public virtual services services { get; set; }
}
If you do not want to alter the ServicesEdition entity definition like i described above, another option is to call the SaveChanges() method after you add the Visit entity and then you can access the Id property of that.
db.visit.Add(visit);
db.SaveChanges();
var visitId = db.Id;
//Now you can use visitId to save other entities
The issue is db.visit.Add(visit); does not generate id until hit db.SaveChanges();
You could add db.SaveChanges(); after db.visit.Add(visit);.
Or you will save as a graph like Shyju explained.
I have data in model and I used to store that data in session as below in controller
if (providerListingModel.ServiceDetails != null && providerListingModel.ServiceDetails.Count > 0)
Session["ServiceDetails"] = providerListingModel.ServiceDetails;
else
Session["ServiceDetails"] = null;
and for retrieving I had used the logic as
if (Session["ServiceDetails"] != null)
{
if (providerListingModel.ServiceDetails == null)
{
List<ServiceDetail> sam = (List<ServiceDetail>)Session["ServiceDetails"];
foreach (var items in sam)
{
var sd = new ServiceDetail();
sd.Id = items.Id;
sd.CategoryServiceId = items.CategoryServiceId;
sd.ServiceType = items.ServiceType;
sd.ServicePrice = items.ServicePrice;
sd.IsSelected = items.IsSelected;
sd.ProviderListingId = providerListingModel.ProviderListingId;
providerListingModel.ServiceDetails.Add(sd);
}
}
Session["ServiceDetails"] = null;
}
The session contains data but on providerListingModel.ServiceDetails.Add(sd); it throw null exception.
ServiceDetails is a class and it contains list of items
namespace xyz.DAL
{
using System;
using System.Collections.Generic;
public partial class ServiceDetail
{
public int Id { get; set; }
public int ProviderListingId { get; set; }
public Nullable<int> CategoryServiceId { get; set; }
public string ServiceType { get; set; }
public Nullable<int> ServicePrice { get; set; }
public string CustomeService { get; set; }
public Nullable<bool> IsSelected { get; set; }
public virtual CategoryService CategoryService { get; set; }
public virtual ProviderListing ProviderListing { get; set; }
}
}
am I missing some code?
As I am new I don't know what I am doing wrong
You are inserting the item to null value, so it throws an error. Create new instance of the list and add an item to collection.
if(providerListingModel.ServiceDetails ==null)
providerListingModel.ServiceDetails = new List<ServiceDetail>();
I have a controller action which saves data to db on change. Model includes children Files, they are not saved to the database however. Data comes ok from the server, file is added to the model from the request ok, but it just won't save. There is no error occuring.
These are my models:
public class Guest
{
public Guest()
{
this.Files = new List<File>();
}
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public string Email { get; set; }
public string Tel { get; set; }
public int CompanyId { get; set; }
public int Votes { get; set; }
public virtual ICollection<File> Files {get; set;}
}
This is my VM
public class GuestViewModel
{
public Guest Guest { get; set; }
public IEnumerable<SelectListItem> Companies { get; set; }
}
and this is the controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit( GuestViewModel guestViewModel, HttpPostedFileBase upload)
{
if (upload != null && upload.ContentLength > 0)
{
var avatar = new File
{
FileName = System.IO.Path.GetFileName(upload.FileName),
FileType = FileType.Picture,
ContentType = upload.ContentType
};
using (var reader = new System.IO.BinaryReader(upload.InputStream))
{
avatar.Content = reader.ReadBytes(upload.ContentLength);
}
guestViewModel.Guest.Files = new List<File> { avatar };
}
if (ModelState.IsValid)
{
Guest guest = new Guest();
guest = guestViewModel.Guest;
_db.Entry(guest).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(guestViewModel);
}
Any help is appreciated.
I think that you have to set the state for the child entities too, because when you attach an entity to a context setting the state directly, any child entities is attacched in "unchanged" state, so is ignored in save changes.
In this case, the state that you need to use for child files is Added.
Hope this helps!
I have been struggling with this for some time. I have a model and an edit view model so I can allow the user to both see the image that was uploaded before and upload a replacement. Everything works fine until I get to the db.Entry portion. The error is:
The entity type EditCardViewModel is not part of the model for the current context.
If I try to add EditCardViewModel to the DbContext, it wants a key and a table, which isn't going to happen. The ViewModel is just a way to pass data. How do I tell it to use the Cards context when saving from this ViewModel?
Controller Edit Get:
public ActionResult Edit(int id = 0)
{
Card card = db.Cards.Find(id);
ViewData["Abilities"] = card.CardAbilities.Select(a => a.AbilityID);
if (card == null)
{
return HttpNotFound();
}
var editview = new EditCardViewModel(card);
{
}
return View(editview);
}
Controller Edit Post:
[HttpPost]
public ActionResult Edit(EditCardViewModel card)
{
if (ModelState.IsValid)
{
if(card.ImageUpload != null)
{
string savedFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images");
savedFileName = Path.Combine(savedFileName, Path.GetFileName(card.ImageUpload.FileName));
card.ImageUpload.SaveAs(savedFileName);
card.Cards.ImageUrl = "\\Images\\" + Path.GetFileName(card.ImageUpload.FileName);
}
db.Entry(card).State = EntityState.Modified; //ERROR - Entity Type is not part of context
db.SaveChanges();
Edit ViewModel:
public class EditCardViewModel
{
public Card Cards { get; set; }
public HttpPostedFileBase ImageUpload { get; set; }
public IEnumerable<SelectListItem> Abilities { get; set; }
public int[] SelectedAbilities { get; set; }
public IEnumerable<SelectListItem> Rarities { get; set; }
public int SelectedRarities { get; set; }
public IEnumerable<SelectListItem> MainTypes { get; set; }
public int SelectedMainTypes { get; set; }
public IEnumerable<SelectListItem> SubTypes { get; set; }
public int SelectedSubTypes { get; set; }
public IEnumerable<SelectList> CardSets { get; set; }
public int SelectedCardSets { get; set; }
public Rarity Rarity { get; set; }
public MainType MainType { get; set; }
public SubType SubType { get; set; }
public CardSet CardSet { get; set; }
public EditCardViewModel() { } //NEEDED OR PARAMETERLESS CONSTRUCTOR ERROR
public EditCardViewModel(Card card) //NEEDED OR CANNOT PASS CARD MODEL
{
Cards = card;
}
}
The problem is that your view model is not recognised by Entity Framework - it has no idea that EditCardViewModel is meant to be a representation of a Card. It's a bit unclear from your view model exactly what you are doing with it but you either need to create a new Card object and use that:
var newCard = new Card
{
Id = card.Id //for example
};
Or possibly use the Cards property of your view model as that is of the correct type.
In my model, I have the following Section class:
public partial class Section
{
public Section()
{
Steps = new List<SectionStep>();
}
public int Id { get; set; }
public int SortId { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public string Html { get; set; }
public Nullable<int> Tutorial_Id { get; set; }
[JsonIgnore]
public virtual Tutorial Tutorial { get; set; }
public virtual ICollection<SectionStep> Steps { get; set; }
[NotMapped]
public bool _destroy { get; set; }
}
and the following SectionStep class:
public class SectionStep
{
public int Id { get; set; }
public int SortId { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public string Html { get; set; }
[JsonIgnore]
public virtual Section Section { get; set; }
[NotMapped]
public bool _destroy { get; set; }
}
I have an ASP.NET application in which users can edit these, including adding and removing Sections and SectionSteps. The data is POSTed to the server via JSON, the server reads this correctly and adds everything just fine. However, when I add two SectionSteps to the same section, I get the following error:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
The JSON POSTed to the server is deserialized into List<Section> sections The following code handles this and adds the appropriate objects to my entity model.
foreach (Section section in sections)
{
if (section._destroy)
{
// if id is 0, it was never even added
if (section.Id > 0)
db.Entry(section).State = EntityState.Deleted;
}
else if (section.Id == 0)
{
db.Entry(section).State = EntityState.Added;
}
else
{
db.Entry(section).State = EntityState.Modified;
}
foreach (SectionStep step in section.Steps.ToList())
{
if (step._destroy)
{
// if id is 0, it was never even added so don't delete
if (step.Id > 0)
db.Entry(step).State = EntityState.Deleted;
else
section.Steps.Remove(step);
}
else if (step.Id == 0)
{
db.Entry(step).State = EntityState.Added;
db.SaveChanges();
}
else
{
db.Entry(step).State = EntityState.Modified;
}
}
}
db.SaveChanges();
returnSections.AddRange(db.Sections.Where(s => s.Tutorial_Id == tutorial_id).OrderBy(s => s.SortId).ToArray());
It seems to me that the problem is that when I add two steps, they both have the same Id for some reason. At first they do start with Id = 0 because I let the database automatically assign that, but I handle the Sections the same way, and adding two Sections works just fine.