ASP.NET Core : moving data from one table into another - html

I'm currently developing an e-commerce website using ASP.NET Core. I'm trying to move data from the Products table into the Items table using a button press so that the data in the items table can be presented on the basket page. Any help would be appreciated.
The relevant button is using the asp-action=AddToCart:
<div class="card-body">
<h3 class="card-title">#product.Name</h3>
<svg class="bd-placeholder-img card-img-top" width="100%" >
<img float="left" width="450" height="450" src="~/assets/Clothing/#product.ProductImage" alt="Image of #product.Name" />
</svg>
<p class="card-text">#product.Description</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
#if (User.IsInRole("Admin"))
{
<a class="btn btn-sm btn-outline-secondary" asp-page="/UpdateProductInfo"
asp-route-id="#product.Id">Update</a>
}
<a class="btn" asp-action="AddToCart">Add to Cart</a>
<p class="float-right card-text" >£#product.Price</p>
</div>
</div>
</div>
C#
[BindProperty]
public Item Items { get; set; }
public IActionResult addToCart()
{
_db.Items.Add(Items);
_db.SaveChanges();
return Page();
}
product.cs model
public class Product
{
public String Id { get; set; }
[ForeignKey("Name")]
public String Name { get; set; }
public String Description { get; set; }
[ForeignKey("Price")]
public int Price { get; set; }
[ForeignKey("ProductImage")]
public String ProductImage { get; set; }
public String ProductImageName { get; set; }
}
Item.cs model
public class Item
{
[Key]
[ForeignKey("Name")]
public String Name { get; set; }
[ForeignKey("Price")]
public int Price { get; set; }
[ForeignKey("ProductImage")]
public String ProductImage { get; set; }
}

item class must be like this :
public class Item
{
[Key]
public int ItemId { get; set; }
public Product Product { get; set; }
[ForeignKey("Product")]
public int ProductId { get; set; }
public String ProductImage { get; set; }
}
and your product class :
public class Product
{
[Key]
public int ProductId { get; set; }
public string Name{ get; set; }
public int Price { get; set; }
public int Description{ get; set; }
public string ProductImage { get; set; }
public string ProductImageName { get; set; }
}
it was a (single to single) relationship between two tables

I'm trying to move data from the Products table into the Items table
using a button press so that the data in the items table can be
presented on the basket page. Any help would be appreciated.
From your description, I assume in the main page, you are listed the Products and each row of the product will have an "Add to Cart" button, after clicking it, it will add the selected Product to the Item table, right?
Since your application is an Asp.net core Razor Page application, for the "Add to Cart" button, you could use the handler method to transfer the route parameter to the method, and then add the selected product to Item table. Refer the following sample:
Model:
public class Product
{
public String Id { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public int Price { get; set; }
public String ProductImage { get; set; }
public String ProductImageName { get; set; }
}
public class Item
{
[Key]
public String Name { get; set; }
public int Price { get; set; }
public String ProductImage { get; set; }
}
ProductIndex.cshtml:
#page
#model RazorPageSample.Pages.ProductIndexModel
<div class="row">
<div class="col-md-6">
<form method="post">
<table class="table">
<thead>
<tr><th colspan="5">Product Table</th></tr>
<tr>
<th>
Product ID
</th>
<th>
Product Name
</th>
<th>
Description
</th>
<th>
Price
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Products)
{
<tr>
<td>
#item.Id
</td>
<td>
#item.Name
</td>
<td class="text-right">
#item.Description
</td>
<td class="text-right">
£#item.Price
</td>
<td class="text-right">
<button asp-page-handler="AddToCart" class="btn btn-primary" asp-route-id="#item.Id">Add to Cart</button>
</td>
</tr>
}
</tbody>
</table>
</form>
</div>
<div class="col-md-6">
<table class="table">
<thead><tr><th colspan="5">Item Table</th></tr>
<tr>
<th>
Item Name
</th>
<th>
Price
</th>
<th></th>
</tr>
</thead>
<tbody>
#if (Model.Items !=null && Model.Items.Count > 0)
{
foreach (var item in Model.Items)
{
<tr>
<td>
#item.Name
</td>
<td class="text-right">
£#item.Price
</td>
<td class="text-right">
</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>
ProductIndex.cshtml.cs:
public class ProductIndexModel : PageModel
{
//Here I use a DataRepository to set the initial data.
private readonly IDataRepository _repository;
public ProductIndexModel(IDataRepository repository)
{
_repository = repository;
}
[BindProperty]
public List<Item> Items { get; set; } //item list.
public List<Product> Products { get; set; } // product list
public void OnGet()
{
Products = _repository.GetProducts();
}
public async Task<IActionResult> OnPostAddToCartAsync(string id)
{
// use session to store the items.
// you could directly store the new item into database. in this scenario, you could query the database and get the existing items.
if (HttpContext.Session.Get<List<Item>>("_Items") != default)
{
Items = (List<Item>)HttpContext.Session.Get<List<Item>>("_Items");
}
if (id != null)
{
var product = _repository.GetProducts().Where(c => c.Id == id).FirstOrDefault();
Item newitem = new Item()
{
Name = product.Name,
Price = product.Price
};
Items.Add(newitem);
HttpContext.Session.Set<List<Item>>("_Items", Items);
}
//reset the Products.
Products = _repository.GetProducts();
return Page();
}
}
The screenshot as below:
More detail information, you could refer the following links:
Handler Methods in Razor Pages
Write a basic form
Session and state management in ASP.NET Core
[Note]If you want to use Session to store the Object,after configuring your application use session, remember to add SessionExtensions.

Related

Change the HTML element in a Blazor application by pressing a button?

I wanted to ask if it is possible to change the type of an HTML element in a Blazor application by pressing a button.
That I turn a normal text into a text input field for example.
I have a table where the first column has a button for each entry in the table.
My goal is that when you press the button, the fields turn into input fields in time, so you can edit the values.
This is just a quick photo edit, but this is how I imagined it.
You can use an index array to track the edit status of each company. When the button is clicked, the corresponding value in the index array will be toggled. If the value is set to true, the cell will display an input field where you can edit the company name. The updated name will be saved to the list.
Instead of using a simple string to store company information, you can create a class that contains multiple properties such as the company name and location..
Output:
Demo: https://blazorfiddle.com/s/lil3olrf
Implementation:
#page "/"
<h3>Companies</h3>
<table class="table table-bordered table-sm">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Company</th>
<th scope="col">Location</th>
</tr>
</thead>
<tbody>
#foreach (var company in Companies)
{
var index = Companies.IndexOf(company);
<tr>
<td>
<button type="button" class="btn btn-primary"
#onclick="#(() => { Edits[index] = !Edits[index]; })">
#(Edits[index] ? "Back" : "Edit")
</button>
</td>
<td>
#if (Edits[index])
{
<input class="form-control" type="text"
style="background-color:lightyellow;"
value="#company.Name"
#oninput="#(e => { Companies[index].Name = e.Value.ToString(); })"/>
}
else
{
#company.Name
}
</td>
<td>
#if (Edits[index])
{
<input class="form-control" type="text"
style="background-color:lightyellow;"
value="#company.Location"
#oninput="#(e => { Companies[index].Location = e.Value.ToString(); })"/>
}
else
{
#company.Location
}
</td>
</tr>
}
</tbody>
</table>
<ul>
#*Check realtime changes to Company names when you edit them*#
#foreach (var company in Companies)
{
<li>#company.Name: #company.Location</li>
}
</ul>
#code {
private List<Company> Companies { get; set; } = new List<Company>
{
new Company("Globex Corporation", "Germany"),
new Company("Soylent Corp", "Switzerland"),
new Company("Umbrella Corporation", "Netherlands")
};
private bool[] Edits { get; set; }
protected override void OnInitialized()
{
Edits = new bool[Companies.Count];
}
public class Company
{
public Company(string name, string location)
{
Name = name;
Location = location;
}
public string Name { get; set; }
public string Location { get; set; }
}
}
Here's a basic component and demo page to demonstrate how you can do this. There's a component and a demo page.
#page "/"
<div>
<button class="btn btn-dark" disabled="#isEdit" #onclick="GoEdit">Edit</button>
#if (this.isEdit)
{
#EditControl
}
else
{
#ViewControl
}
</div>
#code {
[Parameter] public RenderFragment ViewControl { get; set; }
[Parameter] public RenderFragment EditControl { get; set; }
protected string disabled => isEdit ? "disabled": "";
protected bool isEdit { get; set; }
private void GoEdit(MouseEventArgs e)
=> isEdit = !isEdit;
}
And a demo page:
#page "/Demo"
<h3>EditorTest</h3>
<CascadingValue Value="model">
<EditForm EditContext="editContext">
<EditFormState #ref="editFormState" EditStateChanged="EditStateChanged"></EditFormState>
<div>
<SwitchedEditorComponent>
<EditControl>
Email: <InputText #bind-Value="model.Email" placeholder="Enter your Email Address"></InputText>
</EditControl>
<ViewControl>
Email: <InputText #bind-Value="model.Email" disabled></InputText>
</ViewControl>
</SwitchedEditorComponent>
</div>
</EditForm>
</CascadingValue>
#code {
private dataModel model { get; set; } = new dataModel();
private EditFormState editFormState;
private EditContext editContext;
protected override Task OnInitializedAsync()
{
this.editContext = new EditContext(model);
return base.OnInitializedAsync();
}
private void EditStateChanged(bool editState)
{
StateHasChanged();
}
public class dataModel
{
public string Email { get; set; }
}
}

how can I show the record horizontally in view

I have the following record in a view horizontally. I cannot show the the exact layout here. but I hope you can understand what I am looking for the help.
One record under in one column, another record in another column in same row , maximumn 6 column should be shown in each row that means 6 record in each row .
I have the following model
public class Order
{
[Key]
public long id { get; set; }
public DateTime OrderDate { get; set; }
public string Customer { get; set; }
public string Itemname { get; set; }
public int QTY { get; set; }
}
In View I am using IEnumerable. I am trying to list in view the record horizontally in a table under td . maximum 6 record in a row
01/01/2020
02/01/2020
Customer 1
Customer 2
Item1
Item2
You can use bootstrap to specify the number of records per column, such as
<td class="col-xs-2 col-sm-2 col-md-2">
and the following is my demo:
Controller:
public class OrderController : Controller
{
private readonly OrderContext _context;
public OrderController(OrderContext context)
{
_context = context;
}
// GET: Orders
public async Task<IActionResult> Index()
{
var model = new OrderList()
{
OrderLists = await _context.Orders.ToListAsync()
};
return View(model);
}
}
Model:
public class Order
{
[Key]
public long id { get; set; }
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime OrderDate { get; set; }
public string Customer { get; set; }
public string Itemname { get; set; }
public int QTY { get; set; }
}
public class OrderList
{
public IEnumerable<Order> OrderLists { get; set; }
}
View:
#model OrderList
<table class="table">
<tbody>
<tr class="row">
#foreach (var item in Model.OrderLists)
{
<td class="col-xs-2 col-sm-2 col-md-2">
#Html.DisplayFor(modelItem => item.OrderDate)<br />
#Html.DisplayFor(modelItem => item.Customer)<br />
#Html.DisplayFor(modelItem => item.Itemname) <br />
</td>
}
</tr>
</tbody>
</table>
Result:

ASP.NET Core Model null error in the Index view

Please see the Error section below. Other related code is as follows:
Model:
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
BlogPostController
public IActionResult Index()
{
return View("~/Views/BlogsTest/Index.cshtml");
}
View [Index.cshtml]:
#model IEnumerable<ASPCoreCodeFirstApp.Models.Blog>
<p>
<a asp-controller="BlogPost" asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Url)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Url)
</td>
<td>
<a asp-controller="BlogPost" asp-action="Edit" asp-route-id="#item.BlogId">Edit</a>
</td>
<td>
<a asp-controller="BlogPost" asp-action="Create" asp-route-id="#item.BlogId">Edit</a>
</td>
</tr>
}
</tbody>
</table>
Error at #foreach (var item in Model)....line:
I can see the Index method gets called and when I put the breakpoint at the #foreach (var item in Model) line of Index.cshtml file I get Model as null and the browser throws the following error. Blogs table does have data. Even if it did not have data the foreach loop should have returned empty result instead of an NULL exception error. The view relative path in the Index action method seems write since Index.cshtml view does get called. What I may be missing?:
NullReferenceException: Object reference not set to an instance of an object.
MoveNext in Index.cshtml, line 22
Folder Hierarchy:
Model above is in Model.cs file highlighted below:
Your view is a strongly typed view requiring a list (to be precise, IEnumerable) of Blog objects :
#model IEnumerable<ASPCoreCodeFirstApp.Models.Blog>
For strongly typed views, you have to pass an object of the type that the view requires from your controller action for the view engine to be able to render the view ( Even if it's just an empty list ) :
View("ViewName", new List<Blog>())

MVC Radio Button List Grid

I've got an issue trying to read the selected values from the radio button list in my [HttpPost] Controller. Any help would be greatly appreciated.
My models are the following:
public partial class RoleModel
{
public Guid RoleId { get; set; }
public string Description { get; set; }
public List<RoleModuleAccessRight> RoleModuleAccessRights { get; set; }
}
public class RoleModuleAccessRight
{
public string ModuleName { get; set; }
public int ModuleId { get; set; }
public bool HasFullControl { get; set; }
public bool HasReadOnly { get; set; }
public bool HasNoAccess { get; set; }
}
My Controllers:
[HttpGet]
public ActionResult Edit(Guid id)
{
RoleModel role = BusinessLayer.UserManager.GetRoleModel(id);
role.RoleModuleAccessRights = BusinessLayer.UserManager.GetModulesForRoleId(role.RoleId);
return PartialView("_Edit", role);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(RoleModel model)
{
if (ModelState.IsValid)
{
BusinessLayer.UserManager.UpdateAccessRights(model);
string url = Url.Action("List", "Roles");
return Json(new { success = true, url = url });
}
return PartialView("_Edit", model);
}
My View code:
#foreach (RoleModuleAccessRight item in Model.RoleModuleAccessRights)
{
#Html.HiddenFor(model => item.ModuleId)
string radioName = string.Format("RoleModuleAccessRights_{0}", item.ModuleId.ToString());
<tr>
<td>#item.ModuleName</td>
<td>
<div class="checkbox">
#Html.RadioButton(radioName, item.HasFullControl, item.HasFullControl)
</div>
</td>
<td>
<div class="checkbox">
#Html.RadioButton(radioName, item.HasReadOnly, item.HasReadOnly)
</div>
</td>
<td>
<div class="checkbox">
#Html.RadioButton(radioName, item.HasNoAccess, item.HasNoAccess)
</div>
</td>
</tr>
}
The issue im having is that when i post the form im not able to grab the information in my [HttpPost] Controller. It returns "null"
The mark up generated is the following:
Looking at your code, your ids are not unique which is going to break things, also using a dedicated template will simplify your problem. See this example https://stackoverflow.com/a/7668325
Another more generic article: Multiple radio button groups in MVC 4 Razor

need to render html from mvc, only displaying htmls tags not text

I am using razorpdf to generate a pdf report in my mvc 4 application. each time I generate the pdf, the description field will display a bunch of html tags and fields that are not supposed to be shown, i just want the plain text from the description field displayed. does anyone have any advice on how to do this, also any advice on how to add an image into the pdf page as well?
this is my view that is generating the pdf:
#model List<ArdentMC.DHS.COP.Mobile.MVC.Models.Reports>
#{
Layout = "";
}
<!DOCTYPE html>
<html>
<head>
<div style="color=red; align:center;">UNCLASSIFIED/FOR OFFICAL USE ONLY</div>
</head>
<body>
<table style="width:300px;">
#foreach (var item in Model)
{
<tr>
<td>#item.Phase</td>
<td>#item.NocNumber</td>
<td>#item.Title</td>
<td>#item.Location</td>
</tr>
<tr<
<td></td>
<td></td>
<td>#item.ReportDateText</td>
<td>#item.Description</td>
</tr>
}
</table>
<br /><br /><br /><br /><br />
<br /><br /><br /><br /><br />
<div style="color:black; align:center;">US Department of Homeland Security</div>
<br />
<div style="color:red; align:center;">UNCLASSIFIED/FOR OFFICAL USE ONLY</div>
</body>
</html>
this is my model where the information is getting pulled from:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ArdentMC.DHS.COP.Mobile.MVC.Models
{
public class Reports
{
public string NocNumber { get; set; }
public string Title { get; set; }
public Nullable<System.DateTime> IncidentDate { get; set; }
public string ReportDateText { get; set; }
public string IncidentType { get; set; }
public Nullable<int> IncidentSubtypeId { get; set; }
public string IncidentSubtype { get; set; }
public Nullable<int> PhaseId { get; set; }
public string Phase { get; set; }
public string InitialNotification { get; set; }
public string Location { get; set; }
public string NocSpotRep { get; set; }
public string Contributors { get; set; }
public string Participants { get; set; }
public string Description { get; set; }
public Nullable<int> IncidentStateId { get; set; }
public string IncidentState { get; set; }
public Nullable<System.DateTime> PublishDate { get; set; }
public Nullable<System.DateTime> ArchiveDate { get; set; }
}
}
does anyone have some advice on how to just get the description text to display? thank you in advance.
I was able to add
#foreach (var item in Model){
#Html.Raw(item.Description)
} into my view and that rendered the correct code for the description field so that there are no viewable tags, only text.
public ActionResult NotFound() {
Response.ContentType = "text/html";
return View();
}