How to load navigation child items from a controller to view - c#

Am having issues loading navigation(child ) element from a controller to a view
I created this model
public class MultipleItems
{
public IEnumerable<Order> Orders { get; set; }
public IEnumerable<support> Supports { get; set; }
public IEnumerable<DbModel.Track> Tracks { get; set; }
public IEnumerable<Receipt> Receipts { get; set; }
public IEnumerable<Quota> Quotas { get; set; }
}
And the controller
public ActionResult Client()
{
string useremail = User.Identity.GetUserName();
var myModel = new MultipleItems();
myModel.Supports = new SupportW().GetSupports(useremail);
myModel.Orders = new Orders().GetOrders(useremail);
myModel.Receipts = new Receipts().GetReceipts(useremail);
myModel.Tracks = new Track().GetTracks(useremail);
myModel.Quotas = new Quotas().GetQuota(useremail);
return View(myModel);
}
Am interested in Tracks() and this is the method
public IEnumerable<DbModel.Track> GetTracks(string email)
{
try
{
using (var da = new CourierEntities())
{
da.Tracks.Include(a => a.Order);
da.Tracks.Include(a => a.Order.User);
da.Tracks.Include(a => a.destination);
da.Tracks.Include(a => a.Source);
da.Tracks.Include(a => a.CurrentLocation);
var q = (from p in da.Tracks where p.Order.User.Email == email select p).ToList();
if (q != null)
{
return q;
}
}
return null;
}
catch (Exception ex)
{
returnMsg = ex.Message;
return null;
}
}
While the view is
<td>
#if (Model.Orders.Count() != 0)
{
foreach (var i in Model.Tracks)
{
<tr>
Order id #i.OrderID
<br />
Trackid #i.TrackID
<br />
#i.Order.Packagename
</tr>
}
}
</td>
am having issues with #i.Order.Packagename and i recieve this error
The ObjectContext instance has been disposed and can no longer be used for
operations that require a connection.
Description: An unhandled exception occurred during the execution of the
current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.ObjectDisposedException: The ObjectContext
instance has been disposed and can no longer be used for
operations that require a connection.
Source Error:
Line 120:
Line 121: <br />
Line 122: #i.Order.Packagename
Line 123: </tr>

Although the comments suggest the use of a View Model, which would be a good idea, the fundamental issue with your code is the lifetime of the database context(s).
When you execute code such as:
myModel.Supports = new SupportW().GetSupports(useremail);
The object SupportW has a lifetime of that statement. It will likely be disposed before your view executes. If the method GetSupports(useremail) returns IQueryable then when that is resolved in the view, the source is no longer there.
To resolve this you should change the lines to:
myModel.Supports = new SupportW().GetSupports(useremail).ToList();
The addition of the ToList() resolves the `IQueryable' immediately and the data will be available in your view.

Related

Can't update data in database because of Entity validation exception - ASP.Net MVC

I wish to update data found in three related tables in the database. I'm actually sending all the needed data to the database, but can't succeed in updating them. I get the [DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.] SQL Exception.
Below is what I actually have
ViewModel ChauffeurVM:
public class ChauffeurVM
{
public int ChauffeurId { get; set; }
public virtual PERSONNE Personne { get; set; }
public virtual PIECEIDENTITE PieceIdentite { get; set; }
public string NumeroPermis { get; set; }
}
Controller:
public ActionResult ModifierChauffeur(ChauffeurVM ChauffeurVM, HttpPostedFileBase postedPhoto, string Sexe)
{
CHAUFFEUR chauffeur = new CHAUFFEUR();
ChauffeurVM.Personne.Sexe = Sexe;
using (IDAL dal = new Dal())
{
ChauffeurVM.Personne.Photo = dal.UploadandGetImagePath(postedPhoto);
chauffeur.ChauffeurId = dal.UpdateChauffeur(ChauffeurVM);
return RedirectToAction("ListeChauffeur");
}
}
Dal method:
public int UpdateChauffeur(ChauffeurVM chauffeur)
{
CHAUFFEUR c = new CHAUFFEUR();
try
{
c = ChauffeurParId(chauffeur.ChauffeurId);
c.NumeroPermis = chauffeur.NumeroPermis;
bdd.Entry(c).State = EntityState.Modified;
bdd.SaveChanges();
}
catch
{
throw;
}
//Try to assign the value chauffeur.Personne.PersonneId to the pId
int pId = chauffeur.Personne.PersonneId;
c.Personne = new PERSONNE();
PERSONNE p = detailsChauffeurparPersonneId(chauffeur.Personne.PersonneId);
try
{
if (p != null)
{
p.Nom = chauffeur.Personne.Nom;
p.Prenom = chauffeur.Personne.Prenom;
p.Sexe = chauffeur.Personne.Sexe;
p.Telephone = chauffeur.Personne.Telephone;
p.Photo = chauffeur.Personne.Photo;
p.LieuNaissance = chauffeur.Personne.LieuNaissance;
p.DateNaissance = chauffeur.Personne.DateNaissance;
p.CodePostal = chauffeur.Personne.CodePostal;
p.Adresse = chauffeur.Personne.Adresse;
p.Email = chauffeur.Personne.Email;
p.AdresseBoulot = chauffeur.Personne.AdresseBoulot;
p.AdresseDomicile = chauffeur.Personne.AdresseDomicile;
p.PersonneId = chauffeur.Personne.PersonneId;
bdd.Entry(p).State = EntityState.Modified;
bdd.SaveChanges();
}
else
{
}
}
catch
{
throw;
}
try
{
PIECEIDENTITE pi = detailsPieceIdentiteparPersonneId(chauffeur.Personne.PersonneId);
pi.NumeroPiece = chauffeur.NumeroPiece;
pi.LieuDelivrance = chauffeur.LieuDelivrance;
pi.DateDelivrance = chauffeur.DateDelivrance;
pi.DateExpiration = chauffeur.DateExpiration;
pi.Autorite = chauffeur.Autorite;
bdd.Entry(pi).State = EntityState.Modified;
bdd.SaveChanges();
}
catch
{
throw;
}
return c.ChauffeurId;
}
I expect to update the data in the database. But I get the following exception : [DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.]
When I add breakpoints, I succeed in seing all the data send from the form. I can't figure out which field has a null value.
Kindly help, please!
You have a DbEntityValidationException that should point you to the member causing this issue. You should catch the DbEntityValidationException as follows to get the validation messages. Look in the EntityValidationErrors list for further information.
try
{
}
catch(DbEntityValidationException ex)
{
var firstErrorMessage = ex.EntityValidationErrors.First().ValidationErrors.First()
.ErrorMessage;
}

System.InvalidOperationException: Attaching an entity of type 'QC.Models.Defect' failed because another entity of the same type

Look at my code
using (MyBridgeContext context = new MyBridgeContext())
{
context.Users.Attach(user); //both working fine
context.Orders.Attach(order);
foreach (Defect def in defectList.Items)
{
if (defectList.SelectedItem == def)
{
context.Defects.Attach(def);//throwing error
defect = def;
}
}
DefectEntry entry = new DefectEntry();
entry.user = user;
entry.defect = defect;
entry.order = order;
entry.dt = DateTime.Now;
context.Entries.Add(entry);
context.SaveChanges();
this.Content = new MainMonitoring(ref order, ref user);
} <br />
When I am attaching user and order, it works fine even if such objects with their primary key exist in database(THAT IS THE REASON WHY I AM ATTACHING , I am not going to create a new object just attach it to ENTRY). But when I try to attach defect too, it throws that System.InvalidOperationException error.
So this the combobox of Defects:(Program loads the list of defects and when user chooses it, it should be attached to the entry):
private void loadDefects()
{
MyRepository rep = new MyRepository();
var defects = rep.GetDefects();
foreach(var def in defects)
{
defectList.Items.Add(def);
}
defectList.DisplayMemberPath = "Name"; //defectList is comboBox
} <br /> <br />
So this is MyRepository:
public class MyRepository
{
public List<Defect> GetDefects()
{
MyBridgeContext context = new MyBridgeContext();
return context.Defects.AsNoTracking().ToList(); //AsNoTracking doing nothing
}
public List<User> GetUsers()
{
MyBridgeContext context = new MyBridgeContext();
return context.Users.AsNoTracking().ToList();
}
public List<Order> GetOrders()
{
MyBridgeContext context = new MyBridgeContext();
return context.Orders.AsNoTracking().ToList();
}
}

Null Exception thrown in View

Using ASP.NET MVC, .NET Framework 4.5.2, Entity Data Model for SQL DB, Visual Studio 2017.
I have a class generated from the ADO.NET(EF Designer from Database) :
BookInfo.cs
namespace LibraryMS
{
using System;
using System.Collections.Generic;
public partial class BookInfo
{
public string BookID { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public string Publisher { get; set; }
public string PublishDate { get; set; }
public string Edition { get; set; }
public virtual Inventory Inventory { get; set; }
}
}
The database is designed where the "BookID" in the BookInfo table has a foreign key "BookID" in the Inventory table.
In a view to update an inventory's properties referenced by "BookID", I then proceed to query the list and update the correct instance.
Screenshot of update inventory page:
When landing on page to enter info the [HttpGet] UpdateInventory() is called, when clicking "Create" button as seen above, the [HttpPost] UpdateInventory(...) is called.
Logic/Code in Controller:
[HttpGet]
public ActionResult UpdateInventory()
{
return View();
}
[HttpPost]
public async Task<ActionResult> UpdateInventory(string bookID, string ttlIn, string lowin, string outnow)
{
var bf = await SqlRestApiHelper.searchFromBooks(bookID);
bf.Inventory.TotalIn = Convert.ToInt16(ttlIn);
bf.Inventory.LowIn = Convert.ToInt16(lowin);
bf.Inventory.Out = Convert.ToInt16(outnow);
await SqlRestApiHelper.UpdateBookInfoInventory(bf.Inventory);
await SqlRestApiHelper.SaveChanges();
return View("All");
}
[HttpGet]
public async Task<ActionResult> All()
{
return View(await SqlRestApiHelper.getAllBooksInfo(0, 10));
}
SqlRestApiHelper.cs
namespace LibraryMS
{
public static class SqlRestApiHelper
{
private static libraryDBEntities entities = new libraryDBEntities();
public static async Task<LibraryMS.BookInfo> searchFromBooks(string id)
{
return entities.BookInfoes.ToList().Find(book => book.BookID == id);
}
public static async Task UpdateBookInfoInventory(LibraryMS.Inventory inv)
{
var newInv = inv;
var el = entities.BookInfoes.ToList().Find(x => x.Inventory.BookID == newInv.BookID);
if (el != null)
{
el.Inventory.TotalIn = newInv.TotalIn;
el.Inventory.LowIn = newInv.LowIn;
el.Inventory.Out = newInv.Out;
// the above updates the list item referenced
}
}
public static async Task SaveChanges()
{
await entities.SaveChangesAsync();
}
public static async Task<IPagedList<BookInfo>> getAllBooksInfo(int page, int itemsPerPage)
{
List<BookInfo> bookinfo = new List<BookInfo>();
bookinfo = (from o in entities.BookInfoes
orderby o.Title descending //use orderby, otherwise Skip will throw an error
select o)
.Skip(itemsPerPage * page).Take(itemsPerPage)
.ToList();
int totalCount = bookinfo.Count();//return the number of pages
IPagedList<BookInfo> pagebooks = new StaticPagedList<BookInfo>(bookinfo, page + 1,10,totalCount);
return pagebooks;//the query is now already executed, it is a subset of all the orders.
}
The Null Exception Thrown:
Code for all.cshtml view page:
#model PagedList.IPagedList<LibraryMS.BookInfo>
#using PagedList.Mvc;
#{
ViewBag.Title = "All";
}
<h2>all</h2>
<table class="table">
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Author)
</td>
<td>
#Html.DisplayFor(modelItem => item.Publisher)
</td>
<td>
#Html.DisplayFor(modelItem => item.PublishDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Edition)
</td>
<td>
#Html.ActionLink("Details","Details",new { item.BookID})
</td>
</tr>
}
</table>
#Html.PagedListPager(Model, page => Url.Action("All","BookInfoController", new { page }))
your view is throwing error because you are returning the view without passing the model, you are using return View("All") without passing the model
the right way is by passing the model with the view, you can do it this way
View("ViewName", ModelData);
in your case
return View("All", await SqlRestApiHelper.getAllBooksInfo(0, 10));
for the saving part I am not sure why, but i can see few errors,
first what if book does not have inventory info ?
it will throw null error, so first check if null, create new inventory, if not update accordingly
here is how i would do it
public static async Task UpdateBookInfoInventory(Inventory inv)
{
var newInv = inv;
// get book info
var el = entities.BookInfoes.FirstOrDefault(x => x.BookID == inv.BookID);
if (el != null)
{
if(el.Inventory != null)
{
// update accordingly
el.Inventory.TotalIn = newInv.TotalIn;
el.Inventory.LowIn = newInv.LowIn;
el.Inventory.Out = newInv.Out;
// the above updates the list item referenced
}
else
{
/// add new if null
el.inventory = newInv;
}
await SqlRestApiHelper.SaveChanges();
}
As a first step , put the breakpoint in the getAllBooksInfo method and see whether the list count is coming or not in visual studio. This will help you a lot.
And As an alternative step, you can also solve this error by using the ToPagedList(pageIndex, pageSize); method, i have used it personally and it was worked well
ToPagedList example as per your code:
**public static async Task<IPagedList<BookInfo>> getAllBooksInfo(int page, int itemsPerPage)
{
List<BookInfo> bookinfo = new List<BookInfo>();
bookinfo = (from o in entities.BookInfoes
orderby o.Title descending //use orderby, otherwise Skip will throw an error
select o)
.Skip(itemsPerPage * page).Take(itemsPerPage)
.ToList();
int totalCount = bookinfo.Count();//return the number of pages
//changes made to the below line
IPagedList<BookInfo> pagebooks = bookinfo.ToPagedList(1, 10);
return pagebooks;//the query is now already executed, it is a subset of all the orders.
}**
official source:https://github.com/troygoode/PagedList
Note: Even with this approach, kindly check whether you are getting the data or not from the database by using the breakpoint in the changed line.
Hope this will surely solve your problem kindly let me know thoughts or feedbacks
Thanks
karthik

Entityframework ObjectContext instance has been disposed in certain location [duplicate]

This question already has answers here:
Solving "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection" InvalidOperationException
(8 answers)
Closed 5 years ago.
I'm getting the exception:
"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."
Only when I try to add the object or some properties of that object to #Html.ActionLink.
I have reviewed my code couple of times and can't find anything unusual any suggestions on what might be causing this exception?
Thank you!
UserManagerResult.cs
public class UserManagerResult {
public bool Success{get; set;}
public string ErrorMessage{get; set;}
public Account User{get; set;}
public List <Account> UserList{get;}
public UserManagerResult() {
Success = false;
UserList = new List <Account>();
}
}
UserManager.cs
public static UserManagerResult GetUserList() {
UserManagerResult userManagerResult = new UserManagerResult();
try {
using (AlenMotorsDbEntities alenMotorsDbEntities = new AlenMotorsDbEntities()) {
foreach (Account account in alenMotorsDbEntities.Accounts.ToList()) {
userManagerResult.UserList.Add(account);
}
return userManagerResult;
}
}
catch (Exception ex) {
userManagerResult.ErrorMessage = ex.Message;
return userManagerResult;
}
}
DeveloperViewModel.cs
public class DeveloperViewModel {
[Display(Name = "New Role")]
public string NewRole{get; set;}
[Display(Name = "Remove Role")]
public List <SelectListItem> RoleList{get; set;}
[Display(Name = "User list")]
public List <Account> UserList{get; set;}
}
UserManagerController.cs
public ActionResult Developer(DeveloperViewModel model) {
UserManagerResult getUserList = UserManager.GetUserList();
model.UserList = getUserList.UserList.ToList();
return View(model);
}
The view I'm using
#{
foreach (Account account in Model.UserList.ToList()) {
<tr>
<th scope="row">--</th>
<td>#account.Email</td>
<td>#account.LastName</td>
<td>#account.FirstName</td>
<td>
#Html.ActionLink("Remove", "Remove", account)
</td>
</tr>
}
}
In your GetUserList(), try this:
foreach (Account account in alenMotorsDbEntities.Accounts.Include(i=>i.YourOtherEntity).Include(i=>i.AnotherEntity).ToList())
And keep adding all related entities that is relevant.

Object reference not set to an instance of an object error on the controller

I am unsure why I'm getting this error:
Object reference not set to an instance of an object.
I have a db that has some organizations in it, each organization can have multiple domains. the way I have it set up is to have just a regular actionLink to delete a domain. Here is what the code looks like:
public ActionResult DeleteDomain(OrganizationDomainAddressView dd)
{
var org = OrganizationRepo.GetByID(dd.OrganizationID);
if (ModelState.IsValid)
{
org.DomainAddresses.Remove(new OrganizationDomainAddress(dd.OrganizationID, dd.DomainAddress));
OrganizationRepo.Delete(org);
}
OrganizationView orgInfo = (OrganizationView)Mapper.DynamicMap(org, typeof(Organization), typeof(OrganizationView));
var domainList = orgInfo.DomainAddresses;
var ACD = new OrganizationDomainAddressView();
ViewData["ACD"] = ACD;
ViewBag.OrganizationID = dd.OrganizationID;
return PartialView("_EmailDomainPartial", domainList);
}
Here is the View that i'm working with:
#model IEnumerable<AdminTool.Models.ViewModel.OrganizationDomainAddressView>
#using AdminTool.Models.ViewModel;
#{
OrganizationDomainAddressView ACD = (OrganizationDomainAddressView) ViewData["ACD"];
}
<div id="domains">
#foreach (var item in Model)
{
<div class="item">
#item.DomainAddress — #Html.ActionLink("Delete", "DeleteDomain", "Organizations", new { dd = item.DomainAddress })
</div>
}
<div class="item">
#Html.Hidden("OrganizationID", (int)ViewBag.OrganizationID)
</div>
#Html.Partial("_EmailDomainAddPartial", ACD)
</div>
and the viewmodel:
public class OrganizationDomainAddressView
{
public OrganizationDomainAddressView(string domainAddress, int organizationId)
{
DomainAddress = domainAddress;
OrganizationID = organizationId;
}
public OrganizationDomainAddressView()
{ }
[AtLeastOneRequired(ErrorMessageResourceType = typeof(AdminResource), ErrorMessageResourceName = "OrganizationEmailDomainRequired")]
[Display(ResourceType = typeof(AdminResource), Name = "OrganizationValidEmailDomain")]
[RegularExpression(#"#[a-z0-9.-]+\.[a-z]{2,4}", ErrorMessageResourceType = typeof(AdminResource), ErrorMessageResourceName = "OrganizationEmailFormatError")]
public string DomainAddress { get; set; }
public int OrganizationID { get; set; }
}
The code is erroring out on the controller where the line is:
org.DomainAddresses.Remove(new OrganizationDomainAddress(dd.OrganizationID, dd.DomainAddress));
Not sure why this is. Any help would be great!
Based upon the line that the error is raised at, check in the debugger whether the following parts of code are null:
org
org.DomainAdresses
If dd was not set, the error would already appear dome lines above. Depending on your implementation, maybe the constructor of OrganizationDomainAddress throws a NullReferenceException if one of the input values is null.

Categories

Resources