Pass input with route id to controller method together - asp.net

I want to create input with game amount. User will write how many copy of concrete game wants to buy. Then two parameters will pass to AddToCart method. First will be gameId like below (it works well) and user amount input. How to pass these two values together into controller method?
View:
#model IEnumerable
<link rel="stylesheet" href="~/css/productcards.css">
<div class="container">
<div class="row">
#foreach (var game in Model)
{
<div class="col-md-3">
<div class="product-grid">
<div class="product-image">
<a asp-controller="Game" asp-action="ShowDetails" asp-route-productId=#game.GameId>
<img class="pic-1" src="~/images/#game.ImagePath">
</a>
</div>
<div class="product-content">
<h3 class="title">
<a asp-controller="Game" asp-action="ShowDetails" asp-route-productId=#game.GameId>#game.Title</a>
</h3>
<div class="price">#game.Price.ToString() zł</div>
<a asp-controller="Cart" asp-action="AddToCart" asp-route-gameId="#game.GameId" class="btn btn-primary"><i class="fa fa-cart-plus"></i> KUP</a>
</div>
</div>
</div>
}
</div>
</div>
Controller:
public RedirectToActionResult AddToCart(int gameId)
{
var selectedGame = _appDbContext.Games.FirstOrDefault(x => x.GameId == gameId);
if(selectedGame != null)
{
_cart.AddToCart(selectedGame, 1);
}
return RedirectToAction("Index");
}

Change your view like below:
#foreach (var game in Model)
{
<form method="post">
<div class="col-md-3">
<div class="product-grid">
<div class="product-content">
<h3 class="title">
<a asp-controller="Game" asp-action="ShowDetails" asp-route-productId=#game.GameId>#game.Title</a>
</h3>
<div class="price">#game.Price.ToString() zł</div>
<div class="amount"><input name="amount" type="number" /></div> #*add this line*#
</div>
</div>
</div>
<div class="col-md-3">
#*change <a> to <input> and add a <form>*#
<input type="submit" asp-route-gameId="#game.GameId" asp-controller="Cart" asp-action="AddToCart" class="btn btn-primary" value="KUP"/>
</div>
</form>
}
Action:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult AddToCart(int gameId,int amount)
{
//do your stuff...
}
Result:

Related

my update method in Dbset does not working and it just add another row in database

I am trying to learn web development with asp.net 6 and I'm trying to update a category that I created .I've written a get and a post method but it just doesn't working in Edit action and it is adding a new row in database instead of updating.
this is my edit action in category controller
//GET
public IActionResult Edit(int? id)
{
if(id == null || id == 0)
{
return NotFound();
}
var CategoryFromDb = _db.Categories.Find(id);
if (CategoryFromDb == null)
{
return NotFound();
}
return View(CategoryFromDb);
}
//POST
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(Category obj)
{
if (obj.Name == obj.DisplayOrder.ToString())
{
ModelState.AddModelError("name", "The DisplayOrder cannot exactly match the Name.");
}
if (ModelState.IsValid)
{
_db.Categories.Update(obj);
_db.SaveChanges();
return RedirectToAction("Index", "Category");
}
return View(obj);
}
}
this is my Edit.cshtml
#model Category
<form method="post" asp-action="Edit">
<div class="border p-3 mt-4">
<div class="row pb-2">
<h2 class="text-primary">Edit Category</h2>
<hr/>
<div asp-validation-summary="All"></div>
</div>
<div class="mb-3" style=" width: 500px;clear: both;">
<label asp-for="Name"></label>
<input style="width: 100%;clear: both;" asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-bg-danger"></span>
</div>
<div class="mb-3" style=" width: 500px;clear: both;">
<label asp-for="DisplayOrder"></label>
<input style="width: 100%;clear: both;" asp-for="DisplayOrder" class="form-control" />
<span asp-validation-for="DisplayOrder" class="text-bg-danger"></span>
</div>
<button type="submit" class="btn btn-primary" style="width:150px;">Update</button>
<a asp-controller="Category" asp-action="Index" class="btn btn-secondary" style="width:150px">Back to List</a>
</div>
</form>
and this is my category model
public class Category
{
[Key]
public int? CategoryID { get; set; }
[Required]
public string Name { get; set; }
[DisplayName("Display Order")]
[Range (1,100,ErrorMessage ="Not in Range of Display Order")]
public int DisplayOrder { get; set; }
public DateTime CreatedDateTime { get; set; } = DateTime.Now;
}
and this is my index view part that I created Edit button
<div class="w-75 btn-group" role="group">
<a asp-controller="Category" asp-action="Edit" asp-route-id ="#obj.CategoryID" ><i class="bi bi-pencil"></i>Edit</a>
</div>
and it's adding a new row to database instead of updating the database based on the primary key
please help me...
thanks
Your main issue is that you're not filling in the model correctly - namely, your View doesn't fill in the CategoryID, so the controller doesn't "know" which Category to update. You need to modify your View similar to this (I've added the line right below <form>):
#model Category
<form method="post" asp-action="Edit">
#Html.HiddenFor(m => m.CategoryID)
<div class="border p-3 mt-4">
<div class="row pb-2">
<h2 class="text-primary">Edit Category</h2>
<hr/>
<div asp-validation-summary="All"></div>
</div>
<div class="mb-3" style=" width: 500px;clear: both;">
<label asp-for="Name"></label>
<input style="width: 100%;clear: both;" asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-bg-danger"></span>
</div>
<div class="mb-3" style=" width: 500px;clear: both;">
<label asp-for="DisplayOrder"></label>
<input style="width: 100%;clear: both;" asp-for="DisplayOrder" class="form-control" />
<span asp-validation-for="DisplayOrder" class="text-bg-danger"></span>
</div>
<button type="submit" class="btn btn-primary" style="width:150px;">Update</button>
<a asp-controller="Category" asp-action="Index" class="btn btn-secondary" style="width:150px">Back to List</a>
</div>
</form>

Check if IEnumerable list in View Model is null in View

I just wanted to check if it's possible to check if an IEnumerable list is null in the view when passed from the controller via the view model. Or should I only create conditions in the controller?
My code below does not show the else condition.
Apologies if this is painfully obvious to everyone but I'm still only learning and thanks in advance for any pointers in the right direction.
My controller:
[Area("User")]
[Authorize]
public class TrayController : Controller
{
private readonly IUnitOfWork _unitOfWork;
public OfferTrayVM OfferTrayVM { get; set; }
public TrayController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public IActionResult Index()
{
var claimsIdentity = (ClaimsIdentity)User.Identity;
var claim = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier);
OfferTrayVM = new OfferTrayVM()
{
ListOfferTray = _unitOfWork.OfferTray.GetAll(u => u.ApplicationUserId == claim.Value,
includeProperties: "Trade")
};
return View(OfferTrayVM);
}
public IActionResult Delete(int trayId)
{
var tray = _unitOfWork.OfferTray.GetFirstOrDefault(u => u.Id == trayId);
_unitOfWork.OfferTray.Remove(tray);
_unitOfWork.Save();
return RedirectToAction("Index", "Home", new { area = "User" });
}
}
My view model:
public class OfferTrayVM
{
public IEnumerable<OfferTray> ListOfferTray { get; set; }
}
My view:
#model QPQ.Models.ViewModels.OfferTrayVM
<form method="post">
<br />
<div class="container">
<div class="card">
<div class="card-header bg-dark text-light ml-0">
<div class="row">
<div class="col-6 pt-2">
Summary Confirmation
</div>
<div class="col-6 text-end">
</div>
</div>
</div>
#if(Model.ListOfferTray != null)
{
<div class="card-body">
#foreach (var item in Model.ListOfferTray)
{
<div class="row">
<div class="col-12 col-lg-4 pt-md-3">
<h5><strong>#item.Trade.CompanyName - Have offered to trade: </strong></h5>
<p><small>#item.Trade.Description</small></p>
<hr>
<h5><strong>#item.Trade.CompanyName - Have requested in Return: </strong></h5>
<p><small>item.Trade.InReturnFor</small></p>
</div>
<div class="col-12 col-lg-4 pt-md-3">
<h5><strong>You are Offering in return:</strong></h5>
<p><small>#item.OfferInReturn</small></p>
</div>
<div class="col-12 col-lg-4 text-center row">
<div class="col-sm-4 text-right pt-2">
<a asp-action="Delete" asp-route-trayId="#item.Id" class="btn btn-danger">
<i class="bi bi-trash-fill">Delete</i>
</a>
</div>
</div>
</div>
<hr />
}
</div>
}
else
{
<div class="card-body">
<h3>You do not have any existing offers. Please click<a asp-action="index" asp-area="Home">here</a>to continue.</h3>
</div>
}
<div class="card-footer">
<div class="card-footer row">
<div class="col-sm-12 col-lg-4 col-md-6 offset-lg-8 offset-md-6 ">
<a class="btn btn-success form-control">Summary</a>
</div>
</div>
</div>
</div>
</div>
</form>

passing input value to asp-route

Ok so I am trying to pass the value from the input Quantite in the asp-route-qt, but I can't seem to wrap my head around it. This one asp-route-idBillet is working just fine but the other isn't. If anyone could help me solve this problem with an example it would be very much appreciated. Thanks in advance
Edit: I should of specified that the model I am using for the view can't have Quantite as an attribute. The model contains four types of tickets. Each ticket contains a title, a description, a price and an Id. Basically what this means is that I can't use an asp-for tag for the input Quantite.
Here's my view:
<form method="POST">
<div class="row">
#foreach(var billet in Model)
{
<br>
<div class="col-sm-6">
<div class="card">
<div class="card-body">
<h5 class="card-title" asp-for="Titre">#billet.Titre</h5>
<p class="card-text" asp-for="Descript">#billet.Descript</p>
<label for="Quantite">Quantité:</label>
<input type="number" name="Quantite" id="Quantite">
<a class="btn btn-secondary" asp-controller="Billet" asp-action="AjouterBillet" asp-route-idBillet="#billet.Id" asp-route-qt>Ajouter au panier</a>
</div>
</div>
</div>
<br>
}
</div>
<br>
<input type="submit" value="Aller au panier" class="btn btn-primary">
</form>
Here's my controller action
private readonly ZooDbContext _zooDbContext;
private readonly Panier _panier;
public BilletController(ZooDbContext zooDbContext, Panier panier)
{
_zooDbContext = zooDbContext;
_panier = panier;
}
public IActionResult AjouterBillet(int idBillet, int qt)
{
Billet billet = _zooDbContext.Billet.Find(idBillet);
_panier.Ajouter(billet, qt);
return RedirectToAction("Liste");
}
Here's what I found that works.
Here's the view:
<form method="post">
<div class="row">
#foreach(var billet in Model)
{
<br>
<div class="col-sm-6">
<div class="card">
<div class="card-body">
<h5 class="card-title" asp-for="Titre">#billet.Titre</h5>
<p class="card-text" asp-for="Descript">#billet.Descript</p>
#using (Html.BeginForm("AjouterBillet", "Billet"))
{
<label for="Quantite">Quantité:</label>
<input type="number" name="Quantite" id="Quantite">
<input value="Ajouter au panier" type="submit" class="btn btn-secondary" asp-controller="Billet" asp-action="AjouterBillet"
asp-route-idBillet="#billet.Id">
}
</div>
</div>
</div>
<br>
}
</div>
<br>
<a class="btn btn-primary" asp-controller="Panier" asp-action="AfficherPanier">Aller au panier</a>
</form>
Here's is the action:
public class BilletController : Controller
{
private readonly ZooDbContext _zooDbContext;
private readonly Panier _panier;
public BilletController(ZooDbContext zooDbContext, Panier panier)
{
_zooDbContext = zooDbContext;
_panier = panier;
}
[HttpPost]
public IActionResult AjouterBillet(int idBillet, int Quantite)
{
Billet billet = _zooDbContext.Billet.Find(idBillet);
_panier.Ajouter(billet, Quantite);
return RedirectToAction("Liste");
}
}

IFormFile Upload Image ASP.NET core MVC Is showing null value always [duplicate]

This question already has answers here:
how to upload a file to my server using html
(4 answers)
Closed 12 months ago.
So i am building a website where i want to implement a add banner form when the User can Upload his banner image as banner Profile.
And here is where the problem i raise, when i run the code, it return always as null.
Here is my controller:
[HttpPost]
public async Task<ActionResult> AddBannerDataAsync(BannerViewModels abd)
{
if (ModelState.IsValid)
{
string uniqueFileName = null;
if (abd.BannerImg1 != null)
{
string uploadsFolder = Path.Combine(WebHostEnvironment.WebRootPath, "Images");
uniqueFileName = Guid.NewGuid().ToString() + "_" + abd.BannerImg1.FileName;
using (var fs = new FileStream(Path.Combine(uploadsFolder, uniqueFileName), FileMode.Create))
{
await abd.BannerImg1.CopyToAsync(fs);
}
}
Banner bnr = new Banner
{
BannerTitle = abd.BannerTitle,
BannerDescription = abd.BannerDescription,
//BannerImg = abd.BannerImg,
//BannerImg = uniqueFileName,
BannerUrl = abd.BannerUrl,
BannerIndex = abd.BannerIndex
};
_db.Banner.Add(bnr);
_db.SaveChanges();
}
return Redirect("addbanner");
}
Here is my viewmodel:
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using SZGMC.Web.Models;
namespace SZGMC.Web.Areas.Admin.ViewModels
{
public class BannerViewModels
{
public int BannerId { get; set; }
public string BannerTitle { get; set; }
public string BannerDescription { get; set; }
public string BannerImg { get; set; }
public IFormFile BannerImg1 { get; set; }
public string BannerUrl { get; set; }
public string BannerIndex { get; set; }
public int? BMasterId { get; set; }
public byte? IsDeleted { get; set; }
public virtual BannerMaster BMaster { get; set; }
}
}
Here is my view file:
<form asp-controller="Home" asp-action="AddBannerData" method="post" autocomplete="off">
<div id="main-content">
<div class="container-fluid">
<!-- Page header section -->
<div class="block-header">
<div class="row clearfix">
<div class="col-lg-6 col-md-5 col-sm-12">
<h1>Hi, Welcomeback!</h1>
<span>You can add banner here</span>
</div>
<div class="col-xl-6 col-md-7 col-sm-12 text-md-right">
<div class="d-flex align-items-center justify-content-md-end mt-4 mt-md-0 flex-wrap vivify pullUp delay-550">
<div class="mb-3 mb-xl-0 ">
#*Settings*#
<a asp-action="BannerDetails" class="btn btn-dark">Banner List</a>
</div>
</div>
</div>
</div>
</div>
<div class="row clearfix">
<div class="col-12">
<div class="card">
<div class="body">
<div class="header">
<h2><strong>Enter Banner Details</strong></h2>
</div>
<br />
<div class="row">
<div class="col-12">
<div class="form-group c_form_group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"></span>
</div>
<input type="text" class="form-control" asp-for="BannerTitle" placeholder="Banner Title" aria-label="bannertitle" aria-describedby="basic-addon1">
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="form-group c_form_group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"></span>
</div>
<input type="text" class="form-control" asp-for="BannerUrl" placeholder="Banner Url" aria-label="bannerurl" aria-describedby="basic-addon1">
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="form-group c_form_group">
<label>Banner Description</label>
<div class="input-group">
<textarea class="form-control" asp-for="BannerDescription" aria-label="Banner Description" rows="6"></textarea>
</div>
</div>
</div>
<div class="col-6">
<div class="drop-zone">
<span class="drop-zone__prompt">Drop file here or click to upload</span>
<input type="file" asp-for="BannerImg1" name="BannerImg1" class="drop-zone__input" accept="image/*" data-allowed-file-extensions='["jpg", "png" , "jpeg"]' required>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="form-group c_form_group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"></span>
</div>
<input type="text" class="form-control" asp-for="BannerIndex" placeholder="Banner Index" aria-label="bannerindex" aria-describedby="basic-addon1">
</div>
</div>
</div>
<div class="col-6">
<div class="form-group c_form_group">
#Html.DropDownListFor(x => x.BMasterId, ViewBag.MasterBanner as SelectList, "Choose Banner Type", new { #class = "form-control" })
</div>
</div>
</div>
<div class="mb-2" align="center">
<button type="submit" class="btn btn-success btn-round">Add Banner</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
When i try To upload the img in the browser it doesn't Throw any exception, it just doesn't Upload the image to the database and the column is NULL.
thank you in advance to everybody for any help or advice.
you must use enctype="multipart/form-data" attribute on form tag.
<form asp-controller="Home" asp-action="AddBannerData" method="post" autocomplete="off" enctype="multipart/form-data">
<div id="main-content">
....

When model is not valid, return to partial view inside a view, with error message using asp.net core

I´ve got a modal boostrap. I want to show the error of validation on boostrap modal. But when I leave the model empty and click on submit button Its just viewed as a standalone page.
Partial view:
#model WebApplication1.Models.Book
<form asp-controller="Home" asp-action="AddBook"
data-ajax="true" data-ajax-method="POST" data-ajax-mode="replace" data-ajax-update="#frmaddbook">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">Header of Modal</h4>
</div>
<div class="modal-body form-horizontal" id="frmaddbook ">
<span class="alert-danger">
#Html.ValidationSummary()
</span>
<div class="row">
<div class="form-group">
<label asp-for="BookName" class="col-lg-3 col-sm-3 control-label"></label>
<div class="col-lg-6">
<input asp-for="BookName" class="form-control" />
<span asp-validation-for="BookName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="BookDescription" class="col-lg-3 col-sm-3 control-label"></label>
<div class="col-lg-6">
<input asp-for="BookDescription" class="form-control" />
<span asp-validation-for="BookDescription" class="text-danger"></span>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" value="Submit" />
</div>
Index View :
<div class="panel panel-primary">
<div class="panel-body">
<div class="btn-group">
<a class="btn btn-primary marginbutoon" id="showBookgroup" data-toggle="modal" asp-action="AddBook"
data-target="#modal-book">
<i class="glyphicon glyphicon-plus"></i>
Add Book
</a>
</div>
</div>
i use this libraries at top of index view:
jquery.unobtrusive-ajax.min.js
jquery.validate.unobtrusive.min.js
and use at the bottom of index view:
<script src="~/js/book-index.js"></script>
book-index.js:
(function ($) {
function Home() {
var $this = this;
function initilizeModel() {
$("#modal-book").on('loaded.bs.modal', function (e) {
}).on('hidden.bs.modal', function (e) {
$(this).removeData('bs.modal');
});
}
$this.init = function () {
initilizeModel();
}
}
$(function () {
var self = new Home();
self.init();
})
}(jQuery))
Controller:
[HttpGet]
public IActionResult AddBook()
{
var b = new Book();
return PartialView("_AddBook", b);
}
[HttpPost]
[ValidateAntiForgeryToken]
//[HandleError]//not in core
public IActionResult AddBook(Book model)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index");
}
return PartialView("_AddBook", model);
}
Model :
public class Book
{
[Key]
public int BookId { get; set; }
[Display(Name = "Book Name :")]
[Required(ErrorMessage = "Enter Book Name Please ")]
public string BookName { get; set; }
[Display(Name = "Book Description")]
[Required(ErrorMessage = "Enter Book Description Please ")]
public string BookDescription { get; set; }
}
My code is shown above. How can i show validation error in modal partial view ?
You can set the Id of form as the data-ajax-update property value of the form , which is ajaxified. This value will be used as the jQuery selector when the result is received from the ajax call.
#model Book
<form asp-controller="Home" asp-action="AddBook" id="myform"
data-ajax="true" data-ajax-method="POST"
data-ajax-mode="replace" data-ajax-update="#myform">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">Add Book</h4>
</div>
<div class="modal-body form-horizontal" id="frmaddbook ">
<span class="alert-danger">
#Html.ValidationSummary()
</span>
<div class="row">
<div class="form-group">
<label asp-for="BookName" class="col-sm-3 control-label"></label>
<div class="col-lg-6">
<input asp-for="BookName" class="form-control" />
<span asp-validation-for="BookName" class="text-danger"></span>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" value="Submit" />
</div>
</form>
Now when you submit the form and model state validation fails, the action method code will return the partial view result with the validation error messages (generated by the validation helpers) and the jquery.unobtrusive-ajax.js library code will replace (because we specified that with data-ajax-mode="replace") the content of the result of the jquery selector #data-ajax-update (the form tag and it's inner contents) with the response coming back from the server.

Resources