Inventory, OrderItems and Order - c#

The problem I'm facing now is I have multiple Orders and each Order contains multiple items. Each Order has to link to a Client and Each item has to link to a Inventory Item.
Here's my Order Class
public class Order
{
[Key]
public int Id { get; set; }
public int TotalItems { get; set; }
public DateTime DeliveryDate { get; set; }
public string OrderNumber { get; set; }
public int ClientId { get; set; }
[ForeignKey("ClientId")]
public string DeliveryAddress { get; set; }
public List<OrderItem> OrderItems { get; set; }
public Client Clients { get; set; }
}
OrderItem Class
public class OrderItem
{
public int Id { get; set; }
public int OrderId{ get; set; }
[ForeignKey("OrderId")]
public int InventoryInfoId { get; set; }
[ForeignKey("InventoryInfoId")]
[Required]
public string ItemCode { get; set; }
public int Quantity { get; set; }
public InventoryInfo InventoryInfo { get; set; }
public Order Order { get; set; }
}
Any idea of how I can link them?
I think I have solved the above issues
As soon as I process, the next problem pops out.
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(m => item.OrderNumber)
</td>
<td>
#Html.DisplayFor(m=> item.DeliveryAddress)
</td>
<td>
#Convert.ToDateTime(item.DeliveryDate).ToString("dd-MM-yyyy")
</td>
<td>
#Html.DisplayFor(m=>item.Client.ClientCode)
</td>
<td>
#Html.DisplayFor(modelItem => item.TotalItems)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.Id" class="btn btn-success">Edit</a>
<a asp-controller="OrderItem" asp-action="OrderDetail" asp-route-id="#item.Id" class="btn btn-success">Details</a>
<a asp-action="Delete" asp-route-id="#item.Id" class="btn btn-success">Delete</a>
</td>
</tr>
}
This is my Orders Index page, when the details button is been clicked, the page should redirect to OrderItems page. However it doesnot.
#model List<IOSystem.Models.OrderItem>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(m => item.ItemCode)
</td>
<td>
#Html.DisplayFor(m => item.Quantity)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
And here is the error message.
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List1[IOSystem.Models.Order]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.List1[IOSystem.Models.OrderItem]'.
Forgot to add my controller
[HttpPost, ActionName("OrderDetail")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> OrderDetailPost(int? id)
{
if (id == null)
{
return NotFound();
}
var orderItems = await _context.Orders.Include(s=>s.OrderItems).FirstOrDefaultAsync(i => i.OrderItemId == id);
return View(orderItems);
}

Your InvalidOperationException is saying you're passing a List<Order> but the model in your Razor page is a List<OrderItem>
In your controller code:
[HttpPost, ActionName("OrderDetail")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> OrderDetailPost(int? id)
{
if (id == null)
{
return NotFound();
}
var orderItems = await _context.Orders.Include(s=>s.OrderItems).FirstOrDefaultAsync(i => i.OrderItemId == id);
return View(orderItems);
}
You're accessing _context.Orders, which is your Orders table. You're .Include-ing the OrderItems but you're returning your Orders.
Either pass back the OrderItems from var orderItems = ... or adjust your Razor page's Model to be a List<Order>.
If you want to select the OrderItems from your Order in the controller code, update your LINQ statement to:
var orderItems = (await _context.Order
.Include(s => s.OrderItems)
.FirstOrDefaultAsync(i => i.OrderItemId == id))
.Select(x => x.OrderItems); // <-- grab just the OrderItems

Related

ASP NET Core MVC delete row and local file at the same time using Url.Action in <a>

I tried to delete a row by selecting in table in my FileManager View image, but it doesn't work. Nothing happens. Are my HttpGet and HttpPost functions was wrote correctly? Maybe I missed something?
Moreover, I need to delete local file in /wwwroot/storage. How can I do it with deleting a row at the same time? Thank you.
Delete func in my WorkSpaceController
private readonly TextCloudContext Context;
[HttpGet]
public IActionResult Delete(int UserId)
{
Models.File file = Context.Files.SingleOrDefault(f => f.Id == UserId);
return RedirectToAction("FileManager");
}
[HttpPost]
public IActionResult Delete(string Id)
{
int CurrentId = Int32.Parse(Id);
Models.File file = Context.Files.Single(f => f.Id == CurrentId);
Context.Files.Remove(file);
Context.SaveChanges();
return RedirectToAction("FileManager");
}
FileManager view
<table class="table" style="text-align: center">
<tr>
<th>
#Html.ActionLink("File Name", "FileManager", new { sortingOrder = ViewBag.SortingName, Filter_Value = ViewBag.FilterValue })
</th>
<th>
#Html.ActionLink("File Type", "FileManager", new { sortingOrder = ViewBag.SortingExtension, Filter_Value = ViewBag.FilterValue })
</th>
<th>
#Html.ActionLink("Date", "FileManager", new { sortingOrder = ViewBag.SortingDate, Filter_Value = ViewBag.FilterValue })
</th>
<th>
<a>Actions</a>
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Extension)
</td>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
<td>
<a href="#Url.Action("Download", "WorkSpace", new { Name = item.Data })" class="">
<img style="width: 25px;" src="~/Media/MenuIcons/download.png" title="Download"/>
</a>
<a href="#Url.Action("Delete", "WorkSpace", new { UserId = item.Id })">
<img style="width: 25px;" src="~/Media/MenuIcons/delete.png" title="Delete"
onclick="return confirm('Delete this file?')"/>
</a>
</td>
</tr>
}
TextCloudContext.cs
public class TextCloudContext : IdentityDbContext<TextCloudUser>
{
public TextCloudContext(DbContextOptions<TextCloudContext> options)
: base(options)
{
}
public DbSet<File> Files { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
File.cs with get and set values for DbSet in context
public class File
{
public int Id { get; set; }
[Display(Name = "File Name")]
public string Name { get; set; }
public string Data { get; set; }
[Display(Name = "Type")]
public string Extension { get; set; }
[Display(Name = "Date")]
public string Date { get; set; }
public string UserID { get; set; }
public TextCloudUser User { get; set; }
}
FileViewModel as a model of FIles table from DbSet comm in context (created by using a migration)
public int Id { get; set; }
[Display(Name = "FileName")]
public string Name { get; set; }
[Display(Name = "File")]
public IFormFile Data { get; set; }
public string Extension { get; set; }
public string Date { get; set; }
public string UserID { get; set; }
Your Delete action has the could which should delete the record from the database but not the code that deletes a file from the file system. To delete a file from file system, you need to call System.IO.File.Delete method.
Your second problem is that your delete button is a link, so clicking it will issue a GET request which will match the first Delete method (marked with [HttpGet] attribute).
In order to have it issue a POST request you need a form and a submit button.
<form asp-action="Delete" asp-controller="Workspace" asp-route-Id='item.Id' method="post">
<button type="submit" onclick="return confirm('Delete this file?')">
<img style="width: 25px;" src="~/Media/MenuIcons/delete.png" title="Delete" />
</button>
</form>
Note I am using the TagHelpers here which is preferred to the #Url.Action way you were doing.
You don't need post method.your action link requests GET method.
Here is an example on how your get method should look like:
[HttpGet]
public IActionResult Delete(int fileId)
{
Models.File file = Context.Files.FirstOrDefault(f => f.Id == fileId);
if(file != null)
{
Context.Files.Remove(file);
Context.SaveChanges();
if(IO.File.Exists(AbsolutePath of the file)
{
IO.File.Delete(AbsolutePath of the file);
}
}
return RedirectToAction("FileManager");
}

How to pass AnonymousType to asp.net MVC 5 view?

I am trying to pass anonymous type to view but It's get Error to find The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[<>f__AnonymousType1`2[System.Int32,System.Int32]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[Test.Models.BidsDetails]'.
Where my model
public class BidsDetails
{
public int Id { get; set; }
public int BidsId { get; set; }
public int ProductId { get; set; }
public int BidsPrice { get; set; }
public virtual Bids Bids { get; set; }
public virtual Product Product { get; set; }
}
my Controller
[HttpGet]
public ActionResult Winner()
{
TestDbContext db = new TestDbContext();
var result = db.bidsDetails
.GroupBy(g => g.ProductId)
.Select(s => new
{
productId = s.Key,
BidsPrice = s.Max(m => m.BidsPrice)
}).ToList();
return View(result);
}
My view
#model IEnumerable<Test.Models.BidsDetails>
#{
ViewBag.Title = "Winner";
}
<h2>Winner</h2>
<table class="table">
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Bids.Id)
</td>
<td>
#Html.DisplayFor(modelItem => item.Product.ProductName)
</td>
<td>
#Html.DisplayFor(modelItem => item.BidsPrice)
</td>
</tr>
}
</table>
I am beginner to asp.net MVC .
So, How to solve this problem ?

Virtual property is not being set to an instance for product being added to shopping cart

I have an interface that allows products to be added to the shopping cart. If a product not in the cart already, a new Cart object is created and added to the cart. This is the Cart class:
public class Cart
{
[Key]
public int RecordId { get; set; }
public string CartId { get; set; }
public int ProductId { get; set; }
public int Count { get; set; }
public DateTime DateCreated { get; set; }
public virtual Product Product { get; set; }
}
(Notice the virtual Product property.)
If a product being added to the Cart is already in the Cart, then only the Count is incremented for that Cart object:
public void AddItemToCart(Product product)
{
var cartItem = db.Carts.SingleOrDefault(c => c.CartId == ShoppingCartId &&
c.ProductId == product.Id);
if (cartItem == null)
{
cartItem = new Cart
{
ProductId = product.Id,
CartId = ShoppingCartId,
Count = 1,
DateCreated = DateTime.Now
};
db.Carts.Add(cartItem);
}
else
{
cartItem.Count++;
}
db.SaveChanges();
}
However, when viewing the shopping Cart Index, I am getting an error becuase the Product virtual property is not set to instance. The Shopping Cart Index is trying to access the Product.Name, Product.Price properties to display cart records:
#model ValueVille.Models.ShoppingCartViewModel
<table class="panel panel-default table cart-table">
<tr>
<th>
Product Name
</th>
<th>
Price (each)
</th>
<th>
Quantity
</th>
<th>
#Html.ActionLink("Empty", "EmptyCart", "ShoppingCart", "", new { #class = "btn btn-info" })
</th>
</tr>
#foreach (var item in Model.CartItems)
{
<tr id="row-#item.RecordId">
<td>
#item.Product.Name
</td>
<td>
£#item.Product.Price
</td>
<td id="item-count-#item.RecordId">
#item.Count
</td>
<td>
Remove
</td>
</tr>
}
<tr>
<td>
Total
</td>
<td></td>
<td></td>
<td id="cart-total">
£#Model.CartTotal
</td>
</tr>
</table>
This is the ViewModel being loaded on the ShoppingCart Index page:
public class ShoppingCartViewModel
{
public List<Cart> CartItems { get; set; }
public decimal CartTotal { get; set; }
public int CartCount;
}
ShoppingCart Index page controller action:
// GET: ShoppingCart
public ActionResult Index()
{
var cart = ShoppingCart.GetShoppingCart(this.HttpContext);
var Students = db.Carts.Include("Product"); //edit by OP
var viewModel = new ShoppingCartViewModel
{
CartItems = cart.GetCartItems(),
CartTotal = cart.GetTotal(),
CartCount = cart.GetCount()
};
return View(viewModel);
}
This is the cart.GetCartItems() method implementation:
public List<Cart> GetCartItems()
{
return db.Carts.Where(c => c.CartId == ShoppingCartId).ToList();
}
change
public List<Cart> GetCartItems()
{
return db.Carts.Where(c => c.CartId == ShoppingCartId).ToList();
}
to
public List<Cart> GetCartItems()
{
return db.Carts.Include("Product").Where(c => c.CartId == ShoppingCartId).ToList();
}
You need to add a foreign key attribute to the navigation property like so: [ForeignKey("ProductId")]

Related data not showing asp.net c#

After reading this tutorial http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/reading-related-data-with-the-entity-framework-in-an-asp-net-mvc-application I have created some models, controllers and views.
The recipes are showing just fine in the view, but I can't get the RecipeLines to show.
RecipeModel
public class RecipeModel
{
[Key]
public int RecipeId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string ImageUrl { get; set; }
public virtual ICollection<RecipeLine> RecipeLines { get; set; }
}
RecipeLine
public class RecipeLine
{
[Key]
public int RecipeLineId { get; set; }
public int RecipeId { get; set; }
public double Quantity { get; set; }
public UnitOfMeasureModel UnitOfMeasure { get; set; }
public IngredientModel Ingredient { get; set; }
}
RecipeViewModel
public class RecipeViewModel
{
public IEnumerable<RecipeModel> RecipeModels { get; set; }
public IEnumerable<RecipeLine> RecipeLines { get; set; }
}
Recipecontroller
public class RecipeController : Controller
{
private RecipeApplicationDb db = new RecipeApplicationDb();
[HttpGet]
public ActionResult Index(int? id)
{
var viewModel = new RecipeViewModel();
viewModel.RecipeModels = db.Recipes
//.Include(i => i.Name)
.Include(i => i.RecipeLines);
if (id != null)
{
ViewBag.RecipeId = id.Value;
viewModel.RecipeLines = viewModel.RecipeModels.Where(i => i.RecipeId == id.Value).Single().RecipeLines;
}
return View(viewModel);
}
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
RecipeModel recipeModel = db.Recipes.Find(id);
if (recipeModel == null)
{
return HttpNotFound();
}
return View(recipeModel);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
And the view
#model RecipeApplication.Models.RecipeViewModel
#{
ViewBag.Title = "Recepten";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
Naam
</th>
<th>
Omschrijving
</th>
<th>
Afbeelding
</th>
</tr>
#foreach (var item in Model.RecipeModels) {
string selectedRow = "";
if(item.RecipeId == ViewBag.RecipeId)
{
selectedRow = "success";
}
<tr class="#selectedRow" valign="top">
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#if (item.ImageUrl != null)
{
#Html.DisplayFor(modelItem => item.ImageUrl)
}
</td>
<td>
#Html.ActionLink("Select", "Index", new { id = item.RecipeId}) |
#Html.ActionLink("Edit", "Edit", new { id=item.RecipeId }) |
#Html.ActionLink("Details", "Details", new { id=item.RecipeId }) |
#Html.ActionLink("Delete", "Delete", new { id=item.RecipeId })
</td>
</tr>
}
</table>
#if (Model.RecipeLines != null)
{
foreach (var item in Model.RecipeLines)
{
string selectedRow = "";
if (item.RecipeId == ViewBag.id)
{
<p>#item.Quantity #item.UnitOfMeasure #item.Ingredient</p>
}
}
}
When selecting the recipe, the line does get a proper color, and I see an id-value in the URL-string.
If someone could help with this one, that would be awesome.
You're comparing item.RecipeId to ViewBag.id, which doesn't exist. The ViewBag member you set in the controller action was ViewBag.RecipeId.
However, you don't need this conditional at all. All of the recipe lines are already for that recipe id, because you specifically set only those recipe items in Model.RecipeLines.
//change your controller action
[HttpGet]
public ActionResult Index(int? id)
{
if(id == null) return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var model = new RecipeViewModel();
var data = db.RecipeModel.Include(i => i.RecipeLines)
.Where(x=>x.RecipeId == id)
.ToList();
model.RecipeModels = data;
return View(model);
}
//change your viewModel
public class RecipeViewModel
{
public IEnumerable<RecipeModel> RecipeModels { get; set; }
}
//this is in the view
#if (Model.RecipeLines != null)
{
foreach (var item in Model.RecipeModels.RecipeLines)
{
<p>
#item.Quantity
#item.UnitOfMeasure
#item.Ingredient
</p>
}
}

Print Table with List Variable From Entities in MVC

I've not worked MVC for a long time; I'm a fresh guy to this. So, I have these two entities:
// Entity Worker
[Display(Name = "ID")]
public Int32 Id { get; set; }
[Display(Name = "Número")]
public Int32 Numero { get; set; }
[Display(Name = "Nome")]
// Entity Lottery
public Int32 Id { get; set; }
[Display(Name = "Tipo")]
public String Tipo { get; set; }
[Display(Name = "Data")]
public DateTime Data { get; set; }
[Display(Name = "Observações")]
public List<Worker> FuncionariosSorteados { get; set; }
So, for each lottery entity, I will have a List of workers. I am passing the values to the View by the controller, like this:
public ActionResult Details(int id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Lottery lottery = service.FindLottery(id);
if (sorteio == null)
{
return HttpNotFound();
}
return View(lottery);
}
Where the service is my Repository for the connection to database (in this case he do a search by ID on database to get the right lottery.
Here my doubt begin, if I want to do a table for the lotteries, I can do it doing (using Lottery model)
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Tipo)
</td>
<td>
#Html.DisplayFor(modelItem => item.Data)
</td>
<td>
#Html.DisplayFor(modelItem => item.Observacoes)
</tr>
}
But how I can do the same for the public List<Worker> FuncionariosSorteados? I just want to print the public List<Worker> FuncionariosSorteados in a GridMvc table, but through the model I cant have access to it!
I believe you need to iterate through the list within the foreach loop you already created. Something like this:
#foreach (var item in Model)
{
<table>
<tr>
<td>
#Html.DisplayFor(modelItem => item.Tipo)
</td>
<td>
#Html.DisplayFor(modelItem => item.Data)
</td>
<td>
#Html.DisplayFor(modelItem => item.Observacoes)
</td>
</tr>
</table>
<table>
#foreach(var w in Model.FuncionariosSorteados )
{
<tr>
<td>#Html.DisplayFor(w => w.Id)</td>
<td>#Html.DisplayFor(w => w.Numero)</td>
</tr>
}
</table>
}
I'm confused because in your action, you're pulling a single lottery record and passing that to your view, but in your view, you're iterating through what appears to be an IEnumerable<Lottery>.
Since you'd have no issues accessing FuncionariosSorteados off of a Model of type Lottery, I'm assuming the view is actually using IEnumerable<Lottery>. For an enumerable, you have to iterate over the list and access the properties on the individual items. For example:
#model IEnumerable<Lottery>
#Model.FuncionariosSorteados <!-- fail -->
#foreach (var lottery in Model)
{
#lottery.FuncionariosSorteados <!-- success -->
}
For your second entity you could create it like this:
Entitie Lottery
public Lottery( )
{
FuncionariosSorteados = new List <Worker>();
}
public Int32 Id { get; set; }
[Display(Name = "Tipo")]
public String Tipo { get; set; }
[Display(Name = "Data")]
public DateTime Data { get; set; }
[Display(Name = "Observações")]
public virtual List<Worker> FuncionariosSorteados { get; set; }
And thenin your view you can use a foreach loup to iterate inside the lists

Categories

Resources