I have an ASP .Net core MVC 2.0 app where I implemented a shopping cart for an e-commerce site as outlined in this video series. In the app, user can enter search queries for items which are displayed in a table. Each item in the table can be clicked on to display another page that has additional details for that item as well as a add to cart button.
The site features for searching, displaying the item results, and the details page are all implemented as actions in one controller class while the shopping cart functionality is all implemented in a separate controller class.
For some reason, when I click on the "Add to Cart" button for an item, a url of the form http://<hostname>/<controllerName>/<controllerACtion>/<id>is requested, but the corresponding controller action isn't called. This is strange because I'm using essentially the same code to call the action for adding to shopping cart as I did for displaying details. For this reason, I think the issue is related to the setup of the routes.
Here is the route setup in startup.cs:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=resortDeals}/{action=Index}/{id?}");
routes.MapRoute(
name: "shoppingcart",
template: "{controller=ShoppingCartController}/{action=AddToShopingCart}/{id?}");
});
Here is the shopping cart controller structure:
public class ShoppingCartController : Controller
{
public ViewResult Index()
{
...
}
public RedirectToActionResult AddToShopingCart(int dealId)
{
...
}
}
Below is the code for how the action is being called once the add to cart button is clicked:
<div class="addToCart text-right">
<p class="button ">
<a class="btn btn-success" id="cartButton" asp-controller="ShoppingCartController" asp-action="AddToShoppingCart" asp-route-id="#Model.RecNo">
Add to cart
</a>
</p>
</div>
What could be preventing the controller action from being called once the button is clicked?
I had an issue after publishing on the production server, when clicking on the button there was no response and I had to submit the button using Javascript.
<div class="addToCart text-right">
<p class="button ">
<button class="btn btn-success" onclick="search(#Model.RecNo)">
Add to cart
</button>
</p>
</div>
<script>
function addToCart(recNo) {
document.getElementById('cartForm').action = "/ShoppingCart/AddToShoppingCart/" + recNo;
document.getElementById('cartForm').submit();
}
</script>
I don't think you need the following route because the default route will handle the shoppingcart routes as well.
template: "{controller=ShoppingCartController}/{action=AddToShopingCart}/{id?}");
Also, try
<a class="btn btn-success" id="cartButton" asp-controller="ShoppingCart" asp-action="AddToShoppingCart" asp-route-id="#Model.RecNo">
I have removed the Controller word from asp-controller attribute
Also, change the input parameter name of AddToShopingCart method to id instead of dealId
public RedirectToActionResult AddToShopingCart(int id)
{
...
}
Related
my main problem is that I want to change the bootstrap theme of my Website with a Dropdown list of themes and a button.
#model IEnumerable<ProjectManagementTool.ServiceReference1.Theme>
#{
ViewBag.Title = "Settings";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<form action="/Home/Settings" method="get">
<h2>Settings</h2>
<br />
<h4>Change Theme</h4>
#Html.DropDownList("GetThemes", null, htmlAttributes: new { #class = "form-control" })
<br />
<p>
<input class="btn btn-default" type="submit" value="Save"/>
</p>
#foreach (var item in Model)
{
#Html.DisplayFor(modelItem => item.Path)
<br/>
}
</form>
The foreach loop is just to show the diffrent paths.
I have a database aswell with a themes table:
Now the question is, how can I change the bootstrap?
I know that there is this code tho change the theme.
#Styles.Render("~/Content/flatly.bootstrap.css")
But it should be in the _layout.cshtml file to set it for the whole website.
The background is working with a service but this is not important here.
Screenshot of the website:
You could write an action that returns the path of the css file to be used depending on the user settings.
Something along the lines of
#Styles.Render(Html.Action("UserCssPath", "Settings").ToString());
Because you don't have access to a ViewModel in your layout page, the controller must use another mechanism to find out for which user the action was invoked. For example, we store a User Context object with the required data in the HttpContext.Current.Session. This could be written once on logon. The UserCssPath action can then access the DB to find the correct CSS path and return it: return Content(cssPath);
I have an application in Symfony2 that works fine. Now I'm trying to cover a certain part with tests and I've run into trouble with multiple submit buttons and Codeception Symfony2 module.
In the Symfony controller I need to see which submit button the user pressed. I use the following code:
$button = $form->getClickedButton();
if ($button->getName() === 'delete') {
//do stuff
}
And my problem is that $button var is always null when I submit the form form the Cest class. It works fine from the browser. Ive tried both the
$I->submitForm(['id' => 'appbundle_profileEdit'], [], 'appbundle_profileEdit[save]');
method and the
$I->click(['id' => 'appbundle_profileEdit_save'])
method.
The form (just the relevant parts):
<form name="appbundle_profileEdit" method="post" action="" id="appbundle_profileEdit" enctype="multipart/form-data">
<button type="submit" id="appbundle_profileEdit_save" name="appbundle_profileEdit[save]" class="btn-primary btn">
Submit
</button>
</form>
I am working on MVC 5 Asp.Net and following this tutorial. I am wondering how the heck does this fetch the result when I click the Filter button?
There comes a point where this code is added in Movie/view/Index.cshtml
#using (Html.BeginForm())
{
<p> Title: #Html.TextBox("SearchString") <br />
<input type="submit" value="Filter" /></p>
}
Now as far as I know, it creates a textbox and a button on screen. But how is this button calling the search(index) function and passing the value of textbox in the function, I could not get this.
It's not a stupid question. #html.BeginForm() works like this. It has some parameters you could add to it like Action Controller FormType htmlAttributes. The way it works is that if you leave it empty it will look for a post action with the same name that on the page you are now, for example if you are in on the login page, it will look for a login post action. I always write what action and controller I want it to access.
#Html.BeginForm("AddUser", "Admin", FormMethod.Post, new { #class = "my_form"}) {
}
So your post action should accept parameters that your form contains, and that can be a Model ie a Product, ViewModel or single string parameters. In your case with the search your action should look like
[HttpPost]
public ActionResult Search(string SearchString)
{
//do something here
}
Please note here, for the search string to be passed into the method. The name of the <input> has to be the same as the parameter your action takes. So our form should be like this
#using (Html.BeginForm("Search", "YOUR CONTROLLER", FormMethod.Post)){
<p> Title: #Html.TextBox("SearchString") <br />
<input type="submit" value="Filter" /></p>
}
Hope this brings clarity.
I need to display the shopping cart outside of the the HeaderLinks partial which takes the cart items out of the model passed by the CommonController.HeaderLinks action. By creating a new controller with an action that passes the cart info I was able to get the custom ui element from our template working. Right now the controller is inside a custom plugin I got going for some other stuff. The way I see it I have two options:
Leave the controller in the plugin project and live with the fact that if the plugin for some reason is not installed (i.e. a fresh checkout from a new dev.) the theme is going to break, possibly redirecting the user to the error view.
Put the controller in the Controllers folder at Nop.Web with the downside that this would add an extra step to the process of upgrading NopCommerce. If similar issues arise this could get ugly pretty quick.
So my question is: where is the best place to put the controller? Or is there a simpler way to do this thing with the shopping cart?
Regards,
Jose
i will show you a shortcut way to solve it. First create a partial (razor) view e.g _CustomPartialView and then add these usings at the top inside the partial view
#using Nop.Core;
#using Nop.Core.Infrastructure;
#using Nop.Services.Orders;
then next is to query the shopping cart which is easy becuase nopCommerce has already static way of accessing depency resolver method i.e EngineContext.Current.Resolve<T>(). In your case (for shopping cart) it could be the following;
#{
var shoppingCartEnabled = EngineContext.Current.Resolve<Nop.Services.Security.IPermissionService>()
.Authorize(Nop.Services.Security.StandardPermissionProvider.EnableShoppingCart);
var customer = EngineContext.Current.Resolve<IWorkContext>().CurrentCustomer;
int shoppingCartItems = 0;
if (customer.HasShoppingCartItems)
{
shoppingCartItems = customer.ShoppingCartItems
.Where(sci => sci.ShoppingCartType == Nop.Core.Domain.Orders.ShoppingCartType.ShoppingCart)
.LimitPerStore(EngineContext.Current.Resolve<IStoreContext>().CurrentStore.Id)
.ToList()
.GetTotalProducts();
}
if (shoppingCartEnabled)
{
<div class="header-right pull-right wrap-cart hidden-xs ">
<div class="cart-top pull-right">
<div id="cart">
<span class="icon fa fa-shopping-cart"></span>
<div class="heading">
<a href="#Url.RouteUrl("ShoppingCart")" class="ico-cart dropdown-toggle visible-md visible-lg" data-toggle="dropdown" data-hover="dropdown">
<h4 class="cart-label">
#T("ShoppingCart")
<span>#T("ShoppingCart.HeaderQuantity", shoppingCartItems)</span>
</h4>
</a>
</div>
<div class="content">
#if (!String.IsNullOrWhiteSpace(Html.Action("FlyoutShoppingCart", "ShoppingCart").ToString()))
{
<li>#Html.Action("FlyoutShoppingCart", "ShoppingCart")</li>
}
</div>
</div>
</div>
</div>
}
}
Let me know if you need more help :)
I have this HTML code in my view
#using (Ajax.BeginForm("AddJoke", "Home", new AjaxOptions { HttpMethod = "GET", UpdateTargetId = "MyfriendsJokes" , InsertionMode= InsertionMode.InsertAfter}))
{
<div style="display:block">
<textarea placeholder="Post New Joke" id="newJoke" name="joke" rows="3" cols="50" style="float:left;position"></textarea>
<button type="submit" id="postnewjoke" style="float:left"> Post </button>
#Html.TextBoxFor(model => model.fileContent, new { type = "file", id = "fileuploaded", name = "fileuploaded" })
<div style="display:inline-block">
<input type="checkbox" name="geo" id="geo" style="width: 100%; float: left; display: block">
<input name="longitude" style="display:none"/>
<input name="latitude" style="display:none" />
<input name="user" style="display:none" value="#Model.user.Id"/>
<span>Include Location</span>
</div>
<span id="jokeError" style="color:red;font-size:14px;"></span>
</div>
}
<article id="MyfriendsJokes">
#Html.Partial("_NewJoke")
</article>
and this code in my controller
[HttpPost]
public PartialViewResult AddJoke(string joke, string user, HomePage page,HttpPostedFileBase fileuploaded, string longitude, string latitude)
{
Joke newJ = new Joke();
newJ.Key = Guid.NewGuid();
newJ.body = joke;
newJ.facebookID = user;
newJ.rank = 0;
newJ.time = DateTime.Now;
newJ.longitude = longitude;
newJ.latitude = latitude;
db.Jokes.Add(newJ);
HomePage page1 = new HomePage();
page1.user = Session["user"] as MyAppUser;
//db.SaveChanges();
return PartialView("_NewJoke", page1);
}
but instead of adding elements to the targeted div, it reload the page with a new whole page with just the elements of the partial view which is this
#using Jokes.Models
#using Microsoft.AspNet.Mvc.Facebook.Models
#model HomePage
<div style="display:block">
#Model.user.Name
</div>
can someone help and say what's wrong here to append elements to div instead of loading a new whole page?
Make sure that the jquery.unobtrusive-ajax.js script is referenced in your page. This is what AJAXifies all the output generated by the Ajax.* helpers. Without this script you only get a standard <form> element generated by the Ajax.BeginForm with a bunch of data-* attributes. The jquery.unobtrusive-ajax.js script analyzes those data-* attributes and subscribes to the submit event of the form, canceling the default action of making a full postback and sending an AJAX request to the server based on the data-* attributes.
It's important to mention that this script must be included AFTER jquery.js because it depends on it.
Also you seem to have some file input in your form and your controller action is taking an HttpPostedFileBase parameter. You should realize that you cannot upload files using an AJAX request and once you include this script your file uploads will simply stop working. In order to be able to upload files using AJAX you could either use some plugin such as jquery.form and Blueimp file upload or you could directly use the new XMLHttpRequest object that's built into modern browsers. The advantage of the plugins is that they do feature detection and will fallback to other techniques depending on the capabilities of the client browsers.