I have added stripe payment as an Identity folder in my project and I have two tables named OrderHeader and Orderdetails entities in my data base.I created a SD class which has some status and the default status is "Pending_Payment".this status should be updated to Submitted_PaymentApproved in database after placing order,but all of my orders save as Pending_Payment in database .As a result,when I definite to show the list of orderHeaders which are in Inprocess or Submitted status ,it doesnt show me any data but when I change it to pending status it shows.I want to know what should I do to update the status from pending?
public class ManageOrderModel : PageModel
{
private readonly IUnitOfWork _uniOfWork;
public List<OrderDetailVM> OrderDetailVM { get; set; }
public ManageOrderModel(IUnitOfWork unitOfWork)
{
_uniOfWork = unitOfWork;
}
public void OnGet()
{
OrderDetailVM = new();
List<OrderHeader> orderHeaders = _uniOfWork.OrderHeader.GetAll(u => u.Status ==SD.StatusSubmitted || u.Status == SD.StatusInProcess).ToList();
foreach(OrderHeader item in orderHeaders)
{
OrderDetailVM individual = new OrderDetailVM()
{
OrderHeader = item,
OrderDetails = _uniOfWork.OrderDetails.GetAll(u => u.OrderId == item.Id).ToList()
};
OrderDetailVM.Add(individual);
}
}
}
}
this is my view of my razor page block:
#page
#model PracticeWithVideo.Pages.Admin.Order.ManageOrderModel
<h1 class="text-primary py-3">Manage Order's</h1>
<form method="post">
<div class="container row bg-white p-2 mb-3 rounded">
#foreach(var item in Model.OrderDetailVM)
{
<div class="col-12 pb-3 pt-3 mt-4 border rounded">
<div class="row">
<div class="col-4">
Order Number: #item.OrderHeader.Id
<ul class="text-info">
#foreach(var details in item.OrderDetails)
{
<li>#details.Name x #details.Count</li>
}
</ul>
</div>
<div class="col-4 pb-2">
<div class="input-group pb-2">
<div class="input-group-prepend">
<span class="input-group-text bg-secondary border">Time</span>
</div>
<input type="text" value="#item.OrderHeader.PickUpTime" class="form-control" readonly />
</div>
<textarea readonly asp-for="#item.OrderHeader.Comments" class="rounded border form-control" rows="3"></textarea>
</div>
<div class="col-3 offset-1 d-flex align-content-center">
<div class="col-12">
<button type="submit" class="btn btn-primary form-control mb-3">
<i class="bi bi-check-square"></i> Start Cooking
</button>
<button type="submit" class="btn btn-success form-control mb-3">
<i class="bi bi-emoji-laughing"></i> Order Ready
</button>
<button type="submit" class="btn btn-warning form-control mb-3">
<i class="bi bi-x-square-fill"></i> Cancel Order
</button>
</div>
</div>
</div>
</div>
}
</div>
</form>
I change the
List<OrderHeader> orderHeaders = _uniOfWork.OrderHeader.GetAll(u => u.Status ==SD.StatusSubmitted || u.Status == SD.StatusInProcess).ToList();
to
List<OrderHeader> orderHeaders = _uniOfWork.OrderHeader.GetAll(u => u.Status ==SD.StatusPending ).ToList();
and it shows the data because all of my orders saved as Pending_payment in my database.I need to show change the status from pending to submitted after placing order and display the data when I run my project
Related
I am developing a project in asp.net mvc structure.I want to create the detail page of the books I bought from a web service, but I encountered a problem and could not solve it. I need help.
Web Api: https://gutendex.com/
These are the codes for my homepage.
#model BookListModel
<div class="col-md-12">
<div class="row">
#foreach (var books in Model.results)
{
<div class="col-md-3 text-truncate">
<img src="#books.formats.imagejpeg" alt="...">
<div class="card-body">
<h5 class="card-title">#books.title</h5>
</div>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<a class="btn btn-primary stretched-link" asp-controller="Book" asp-action="Details" asp-route-id="#books.id">Details</a>
<button type="button" class="btn btn-sm btn-outline-secondary">Add</button>
</div>
</div>
<br />
</div>
}
</div>
</div>
public class BookRepository
{
private static List<Result> results;
public static Result GetBooksById(int id)
{
return results.FirstOrDefault(b => b.id == id); // PROBLEM HERE
}
}
public IActionResult Details(int id)
{
return View(BookRepository.GetBooksById(id));
}
#model Result
<div class="card mb-3">
<div class="card-body">
<div class="row no-gutters">
<div class="col-md-3">
<img src="#Model.formats.imagejpeg" class="card-img">
</div>
<div class="col-md-9">
<h5 class="card-title">#Model.title</h5>
<p class="card-text">#Model.subjects</p>
<p class="card-text">
<small class="text-muted">3 days ago</small>
</p>
</div>
</div>
</div>
</div>
I wrote a book repository class to help me, the id of the book comes from there with the help of a button, but my method returns a null value.
It gives an error here, it returns null.
Your private static List<Result> results; is null. You should initialized that at some point/somewhere. Or load data into it, whatever is your intent. At least that is what the errors indicates, FirstOrDefault is an extensions method called on the collection, but that fails if said collection is null. And your code does not show if it is initialized somewhere.
i.e.
results = new List<Result> { new Result(...) }
I'm having trouble with a list within my model returning as null even tho in the view it clearly has some value.
I had trouble trying to add objects to my model's list, someone helped me and my problem was half solved. This is the code I came up with after the help
My view:
#model ActivityForm
#{
ViewData["Title"] = "Activity Details";
}
<section class="my-sm-5">
<div class="container">
<div class="section-header d-flex mb-5">
<h1 class="h-02 flex-grow-1">Activity Details</h1>
</div>
<div class="row">
<div class="col-md-7">
<div class="section-header d-flex mb-5">
<h1 class="h-04 flex-grow-1">Form</h1>
</div>
<form id="form" class="row g-3 w-90" asp-action="Create">
<div class="col-md-12">
<label asp-for="Name" class="form-label">#Html.DisplayNameFor(model => model.Name)</label>
<input asp-for="Name" type="text" class="form-control" id="inputEmail4"
placeholder="#Html.DisplayNameFor(model => model.Name)">
<span asp-validation-for="Name" class="invalid-feedback"></span>
</div>
<div class="col-12">
<label asp-for="Description" class="form-label">#Html.DisplayNameFor(model =>
model.Description)</label>
<textarea asp-for="Description" class="form-control" id="exampleFormControlTextarea1" rows="5"
placeholder="#Html.DisplayNameFor(model => model.Description)"></textarea>
<span asp-validation-for="Description" class="invalid-feedback"></span>
</div>
<div class="col-md-4">
<label asp-for="StartDate" class="form-label">#Html.DisplayNameFor(model =>
model.StartDate)</label>
<input asp-for="StartDate" type="date" class="form-control"
placeholder="#Html.DisplayNameFor(model => model.StartDate)">
<span asp-validation-for="StartDate" class="invalid-feedback"></span>
</div>
<div class="col-md-4">
<label asp-for="EndDate" class="form-label">#Html.DisplayNameFor(model => model.EndDate)</label>
<input asp-for="EndDate" type="date" class="form-control"
placeholder="#Html.DisplayNameFor(model => model.EndDate)">
<span asp-validation-for="EndDate" class="invalid-feedback"></span>
</div>
<div class="col-md-4 mb-6">
<label asp-for="Points" class="form-label">#Html.DisplayNameFor(model => model.Points)</label>
<input asp-for="Points" type="number" class="form-control"
placeholder="#Html.DisplayNameFor(model => model.Points)">
<span asp-validation-for="Points" class="invalid-feedback"></span>
</div>
<div class="col-8 d-grid gap-2">
<a class="btn btn-primary mb-2" data-bs-toggle="modal" data-bs-target="#add-award">Add award</a>
<div class="row">
<div class="col-md-6">
<a class="btn btn-outline-primary w-100" data-bs-toggle="modal"
data-bs-target="#cancel-activity">Cancel</a>
</div>
<div class="col-md-6">
<a class="btn btn-outline-primary w-100" data-bs-toggle="modal"
data-bs-target="#post-activity">Post Activity</a>
</div>
</div>
</div>
<div class="modal" id="add-award" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content br-20 pd-20">
<div class="modal-header justify-content-center">
<h5 class="modal-title h-04 text-prim-color">Award details</h5>
</div>
<div class="row g-3">
<div class="modal-body">
<div class="row g-3">
<div class="col-md-12">
<label asp-for="Award.Name" class="form-label">Name</label>
<input asp-for="Award.Name" type="text" class="form-control"
id="award-name">
</div>
<div class="col-12">
<label asp-for="Award.Description" for="inputAddress"
class="form-label">Description</label>
<textarea asp-for="Award.Description" class="form-control"
id="award-description" rows="5"></textarea>
</div>
</div>
</div>
<div class="modal-footer justify-content-center">
<button type="button" class="btn btn-outline-primary w-100"
data-bs-dismiss="modal">Close</button>
<input class="btn btn-primary w-100" type="submit" value="Confirm"></input>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="col-md-5">
<div class="section-header d-flex mb-5">
<h1 class="h-04 flex-grow-1">Awards</h1>
</div>
<table class="table">
<thead>
<tr>
<th scope="col">Award name</th>
<th scope="col">Description</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
#if (Model.Awards != null)
{
foreach (var item in Model.Awards)
{
<tr>
<td>#item.Name</td>
<td>#item.Description</td>
<td>
<a class="btn btn-outline-primary btn-sm">Edit</a>
<a class="btn btn-outline-primary btn-sm">Remove</a>
</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>
</div>
</section>
Method in controller:
[HttpPost]
public async Task<IActionResult> Create(ActivityForm data)
{
var award = data.Award;
if (award.Name != null && award.Description != null)
{
if (data.Awards == null) data.Awards = new List<AwardForm>();
data.Awards.Add(new AwardForm { Name = award.Name, Description = award.Description });
data.Award.Name = "";
data.Award.Description = "";
return View(data);
}
if (!ModelState.IsValid)
{
return View(data);
}
string userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
await service.NewActivityAsync(data, userId);
return RedirectToAction(nameof(Index));
}
Model
public class ActivityForm
{
public string Name { get; set; }
public string Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int Points { get; set; }
public AwardForm Award { get; set; }
public List<AwardForm> Awards { get; set; }
}
Everything was now working as intended but I had one more issue left. When I try to add another Award to the list, the list is returned to the controller method as null.
I'm not really sure if the issue is related to binding, I have noticed that every other value is bound and is returning the expected value except the list which is not bound.
Change the foreach loop to:
<tbody>
#if (Model.Awards != null)
{
#for (var i = 0; i < Model.Awards.Count; i++)
{
<input type="hidden" asp-for="#Model.Awards[i].Name" />
<input type="hidden" asp-for="#Model.Awards[i].Description" />
<tr>
<td>#Model.Awards[i].Name</td>
<td>#Model.Awards[i].Description</td>
<td>
<a class="btn btn-outline-primary btn-sm">Edit</a>
<a class="btn btn-outline-primary btn-sm">Remove</a>
</td>
</tr>
}
}
</tbody>
This has same effect to what #Victor suggested but using input tag helper instead of html helper.
Documentation for binding model to a collection: https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0#collections-1
Also your form should wrap around both Form and Awards sections:
<form id="form" class="row g-3 w-90" asp-action="Create">
<div class="col-md-7">
<div class="section-header d-flex mb-5">
<h1 class="h-04 flex-grow-1">Form</h1>
</div>
...
</div>
<div class="col-md-5">
<div class="section-header d-flex mb-5">
<h1 class="h-04 flex-grow-1">Awards</h1>
</div>
...
</div>
</form>
The list binding context should include indexes to work properly.
Add to following code located below right after declaration of the <form> tag:
<form id="form" class="row g-3 w-90" asp-action="Create">
#if (Model.Awards != null)
{
for (int i=0; i < Model.Awards.Count; i++)
{
#Html.Hidden("Awards[" + i + "].Name", Model.Awards[i].Name)
#Html.Hidden("Awards[" + i + "].Description", Model.Awards[i].Description)
}
}
... your markup and control that performs the submit are located here
</form>
To be a part of the binding context these hidden fields should be declared inside the <form> from that the submit is performing.
Even though the model is not null the required html is not rendered. This is my razor view:
#model List<Product>
#{
ViewBag.Title = "Cart";
}
#for(int i=0;i<=Model.Count()-1;i++)
{
<p>foreach triggered</p>
var image = "~/images/" + Model[i].product_image_path;
<div class="row">
<div class="col">
<div class="row">
<div class="col-md-2">
<img src="#image" alt="No image" class="img-fluid" width="60" asp-append-version="true" />
</div>
<div class="col-md-4">
<div class="row">
<div class="col">
<p class="justify-content-md-start">#Model[i].ProductName</p>
</div>
</div>
<div class="row">
<div class="col">
<p>₹#Model[i].Price</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="row">
<div class="col-md-8">
#*change quantity button*#
<div class="input-group">
<button type="submit" class="btn btn-light"> - </button>
<input type="text" class="form-control" value="#Model[i].Quantity" readonly />
<button type="submit" class="btn btn-light"> + </button>
</div>
</div>
</div>
<br />
</div>
<div class="col-md-2">
<div class="row">
<div class="col">
<button class="btn btn-danger" type="button" id="button-minus">Remove</button>
</div>
</div>
</div>
</div>
</div>
</div>
}
Here is my get action method. This is basically retrieving the product from the models. I am returning an object of List<Product>. Trying to loop over it using for loop on razor view does not seem to work.
[HttpGet]
public IActionResult Cart()
{
var model = new CartProductViewModel();
var sessionId = HttpContext.Session.Id;
var allCartItems = context.cartItems;
var allProducts = context.products;
var currentCartItem = allCartItems.Where(p => p.Product.ProductId.Equals(sessionId)).Select(p=>p).ToList();
List<Product> products = new List<Product>();
foreach (var item in currentCartItem)
{
var id = item.Product.ProductId;
if (id is null) { return View("NotFound"); }
Product prod = allProducts.Where(p => p.ProductId.Equals(id)).Select(p=>p).Single();
products.Add(prod);
}
return View(products);
}
I have a form that displays a persons title and name.It shows a lot more than that, but this is the bit I am asking about.
I have a person table.
If the user wants to change the person details, is it possible to open up a pop up modal form that lists all the persons in the person table, so that the user can either select an existing person, or insert a new person and when the user closes the pop up, the main form is populated with the selected/new persons details?
I am using ASP.NET Core MVC 5 and EF Core 5.
Any help or pointing to a tutorial would be a great help, thanks.
UPDATE -
I have tried the following -
I have created a modal partial view -
#model Person
<div class="modal fade" id="personModal" >
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="personModalLabel">Persons</h4>
<button type="button" class="close" data-dismiss="modal">
<span>x</span>
</button>
</div>
<div class="modal-body">
<form action="Create">
<table class="table table-bordered table-striped table-hover">
<tbody>
#foreach (var pers in ViewBag.PersonList)
{
<tr>
<td style="display:none">#pers.Id</td>
<td class="text-left">
<a asp-action="details" asp-controller="admin" asp-route-id="#pers.Id" title="Click to select vaccination centre">#pers.Title.Description</a><br />
</td>
<td class="text-left ">
#pers.Forename
</td>
<td class="text-left ">
#pers.Surname
</td>
</tr>
}
</tbody>
</table>
<br />
<div class="form-row">
<label asp-for="TitleId" class="control-label col-md-2">Title</label>
<div class="col-md-4 mb-2">
<select asp-for="TitleId" asp-items="#(new SelectList(ViewBag.TitleList, "Id", "Description"))" style=" width: 363px; height: 37px"></select>
<span asp-validation-for="TitleId" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<label asp-for="Forename" class="control-label col-md-2">Forename</label>
<div class="col-md-4 mb-2">
<input asp-for="Forename" class="form-control" maxlength="100" />
<span asp-validation-for="Forename" class="text-danger"></span>
</div>
</div>
<div class="form-row">
<label asp-for="Surname" class="control-label col-md-2">Surname</label>
<div class="col-md-4 mb-2">
<input asp-for="Surname" class="form-control" maxlength="100" />
<span asp-validation-for="Forename" class="text-danger"></span>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-save="modal">Save</button>
</div>
</div>
</div>
</div>
I have added the following script to site.js -
$(function () {
var placeHolderElement = $('#PlaceHolderHere');
$('button[data-toggle="ajax-modal"]').click(function (event) {
var url = $(this).data('url');
$.get(url).done(function(data) {
placeHolderElement.html(data);
placeHolderElement.find('.modal').modal('show');
})
})
placeHolderElement.on('Click', '[data-save="modal"]', function (event) {
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var sendData = form.serialize();
$.post(actionUrl, sendData).done(function (data) {
placeHolderElement.find('.modal').modal('hide');
})
})
})
And the controller -
[HttpGet]
public IActionResult Create()
{
List<Person> personList = _personRepository.Persons.ToList();
ViewBag.PersonList = personList;
List<Title> titleList = _titleRepository.Titles.ToList();
ViewBag.TitleList = titleList;
Person pers = new Person();
return PartialView("_PersonModalPartial", pers);
}
[HttpPost]
public IActionResult Create(Person pers)
{
_personRepository.CreatePerson(pers);
List<Person> personList = _personRepository.Persons.ToList();
ViewBag.PersonList = personList;
List<Title> titleList = _titleRepository.Titles.ToList();
ViewBag.TitleList = titleList;
return PartialView("_PersonModalPartial", pers);
}
I call the modal with the the following in my main form -
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#personModal"
data-url="#Url.Action("Create")" >Insert</button>
The above code shows the modal and populates the table.
However nothing happens when you press save!?
UPDATE 2 -
I changed the button in the modal for to
input type="submit" value="Submit" name="Submit" class="btn btn-success float-right" id="SubmitForm" />
And then changed the form tag in my modal form to -
<form method="post" asp-controller="Admin" asp-action="Create">
That worked.
Now I am wondering how you can pass the id value of the model into the Modal form using the data-url part of the calling button?
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#personModal"
data-url="#Url.Action("Create")" >Insert</button>
You can use #Url.Action("Create",new { id=xxx}),here is a demo:
Html(I use "sss" as a sample data of id):
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#personModal"
data-url="#Url.Action("Create1",new { id="sss"})">
Insert
</button>
js:
$('button[data-toggle="ajax-modal"]').click(function (event) {
var url = $(this).data('url');
$.get(url).done(function (data) {
placeHolderElement.html(data);
placeHolderElement.find('.modal').modal('show');
})
})
Controller:
public IActionResult Create1(string id) {
return Ok();
}
result:
Update:
If you want to use #Model.Id:
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#personModal"
data-url="#Url.Action("Create1",new { id=Model.Id})">
Insert
</button>
I have a Razor Index page with a button, that when clicked should run an action on the Home Controller, but when I debug the home controller, the action is not firing and the break point not being hit.
The Razor code is:
#{
ViewBag.Title = "csi media web test";
}
<div class="jumbotron">
<h1>csi media web test</h1>
<p class="lead">Liane Stevenson</p>
</div>
<div class="row">
<div class="col-md-12">
<div class="panel panel-info">
<div class="panel-heading"><i class="glyphicon glyphicon-arrow-right"></i> Enter Your Four Numbers</div>
<div class="panel-body">
<form class="form-inline">
<div class="col-md-9">
<div class="form-group">
<label class="sr-only" for="number1">1st Number</label>
<input type="number" class="form-control" id="number1" name="Number1" placeholder="#1">
</div>
<div class="form-group">
<label class="sr-only" for="number2">2nd Number</label>
<input type="number" class="form-control" id="number2" name="Number2" placeholder="#2">
</div>
<div class="form-group">
<label class="sr-only" for="number3">3rd Number</label>
<input type="number" class="form-control" id="number3" name="Number3" placeholder="#3">
</div>
<div class="form-group">
<label class="sr-only" for="number4">4th Number</label>
<input type="number" class="form-control" id="number4" name="Number4" placeholder="#4">
</div>
</div>
<div class="col-md-3 text-right">
<button class="btn btn-default" onclick="location.href='#Url.Action("SortDesc", "Home")'"><i class="glyphicon glyphicon-arrow-down"></i> Sort Desc</button>
<button class="btn btn-default" onclick="location.href='#Url.Action("SortAsc", "Home")'"><i class="glyphicon glyphicon-arrow-up"></i> Sort Asc</button>
</div>
</form>
<p>
#if (Model != null)
{
foreach (int number in Model.Numbers)
{
<span class="label label-info">#number</span>
}
}
</p>
</div>
</div>
</div>
</div>
And the Action is:
public ActionResult SortDesc (string number1, string number2, string number3, string number4)
{
NumberSetList list = new NumberSetList();
List<int> numbers = new List<int>();
numbers.Add(Convert.ToInt32(number1));
numbers.Add(Convert.ToInt32(number2));
numbers.Add(Convert.ToInt32(number3));
numbers.Add(Convert.ToInt32(number4));
numbers.OrderByDescending(i => i);
list.SortOrder = "Desc";
return View(list);
}
When it runs it does however change the URL of the page to:
http://localhost/Home/Index?number1=5&number2=4&number3=3&number4=9
So it's almost as if it knows the action is there and what it takes but it just doesn't run it?
What you need is a anchor tag and not a button. Having a link on a tag will actually change the browser URL to the value given in its href. Where as a button will do nothing. To change the URL you will have to add additional Javascript to handle it.
So change this
<button class="btn btn-default" onclick="location.href='#Url.Action("SortDesc", "Home")'">
<i class="glyphicon glyphicon-arrow-down"></i> Sort Desc
</button>
to
<a class="btn btn-default" href="#Url.Action("SortDesc", "Home")">
<i class="glyphicon glyphicon-arrow-down"></i> Sort Desc
</a>
Do the same changes to your other button syntax too.
This code is pseudo code and is untested but this should give you an idea
put this in your models folder
public class myViewModel
{
public int Number1 {get; set;}
public int Number2 {get; set;}
public int Number3 {get; set;}
public int Number4 {get; set;}
}
change your controller to something like this
[HttpPost]
public ActionResult SortDesc (myViewModel model)
{
if(!ModelState.IsValid)
{
return View(list)
}
else
{
NumberSetList list = new NumberSetList();
List<int> numbers = new List<int>();
numbers.Add(model.Number1);
numbers.Add(model.Number2));
numbers.Add(model.Number3));
numbers.Add(model.Number4));
numbers.OrderByDescending(i => i);
list.SortOrder = "Desc";
return View(list);
}
}
this will tell you if your model is valid or not, but I suspect your data is being passed and read as an integer rather than a string, so you could try changing the object type first and then try model binding
but on a review of my code just then, you might be missing the [HttpPost] attribute at the start of the code block which would mean this is always a HttpGet