-
Notifications
You must be signed in to change notification settings - Fork 813
Create update-cart #6523
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Create update-cart #6523
Changes from 1 commit
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
fa9c8d8
Create update-cart
mr-shellychauhan 3cdfa12
Update 13/umbraco-commerce/how-to-guides/update-cart
mr-shellychauhan a62bc48
Update 13/umbraco-commerce/how-to-guides/update-cart
mr-shellychauhan 639163d
Correct grammar and more context
sofietoft 34f1b71
Rename update-cart to update-cart.md
mr-shellychauhan 7456b75
Update 13/umbraco-commerce/how-to-guides/update-cart.md
mr-shellychauhan 99ae6e3
Update 13/umbraco-commerce/how-to-guides/update-cart.md
mr-shellychauhan 8450bd3
Attempt to fix the long sentence
sofietoft 3bdfdfe
Shortened another sentence
sofietoft cd19775
Small update to trigger GitBook checks
sofietoft File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,203 @@ | ||
| --- | ||
| description: How-To update your cart. | ||
| --- | ||
|
|
||
| Once an item has been added to the cart you would most likely need the functionality to update the cart. | ||
|
|
||
| ## Update shopping cart | ||
| You will need a new page for the user to navigate to giving a summary of what's already in the cart and the ability to update each item. | ||
|
|
||
| Create a new View, we will call it `cart.cshtml` with the below code | ||
|
|
||
| ```csharp | ||
| @inherits UmbracoViewPage | ||
| @{ | ||
| var store = Model.Value<StoreReadOnly>("store", fallback: Fallback.ToAncestors); | ||
| var currentOrder = CommerceApi.Instance.GetCurrentOrder(store!.Id); | ||
| if (currentOrder == null) return; | ||
| } | ||
| ``` | ||
|
|
||
| - You will need to access the store in order to have access to the relevant data for the current cart/order. The store has a `fallback` property allowing you to traverse up the tree to find the store. | ||
| - `currentOrder` is used to get the current order for the store. If the current order is null then theres nothing to display. | ||
|
|
||
| To display the basic layout when an order does exist, we need to add some markup or at least amend it to include the desired functionality. In the same file add the below | ||
|
|
||
| ```csharp | ||
| @using (Html.BeginUmbracoForm("UpdateCart", "CartSurface")) | ||
| { | ||
| @foreach (var item in currentOrder.OrderLines.Select((ol, i) => new | ||
| { | ||
| OrderLine = ol, | ||
| Index = i | ||
| })) | ||
| { | ||
| <p> | ||
| @Html.Hidden($"orderLines[{item.Index}].Id", item.OrderLine.Id) | ||
| @item.OrderLine.Name @Html.Hidden($"orderLines[{item.Index}].Quantity", (int)item.OrderLine.Quantity, new { @type = "number" }) | ||
mr-shellychauhan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| @Html.Hidden($"orderLines[{item.Index}].ProductReference", item.OrderLine.ProductReference) | ||
| <a href="@Url.SurfaceAction("RemoveFromBasket", "BasketSurface", new { OrderLineId = item.OrderLine.Id })">Remove</a> | ||
| </p> | ||
|
|
||
| } | ||
|
|
||
| <button type="submit">Update Cart</button> | ||
|
|
||
| var success = TempData["SuccessMessage"]?.ToString(); | ||
|
|
||
| if (!string.IsNullOrWhiteSpace(success)) | ||
| { | ||
| <div class="success">@success</div> | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| We first loop through each item in the `cart/order` and display the name of the product and the quantity. We also add a hidden input for the order id, quantity and product reference. This is so we can update the cart with the new quantity. | ||
|
|
||
| ```csharp | ||
| @Html.Hidden($"orderLines[{item.Index}].OrderId", item.OrderLine.Id) | ||
| ``` | ||
|
|
||
| This is setting the Id of the order line (or the item in the current cart/order). | ||
|
|
||
| ```csharp | ||
| @item.OrderLine.Name @Html.Hidden($"orderLines[{item.Index}].Quantity", (int)item.OrderLine.Quantity, new { @type = "number" }) | ||
| ``` | ||
|
|
||
| As well as setting the name of the product, this is setting the quantity of the product in the cart/order. Finally the quantity is set to a number input type. | ||
|
|
||
|
|
||
| ```csharp | ||
| @Html.Hidden($"orderLines[{item.Index}].ProductReference", item.OrderLine.ProductReference) | ||
| ``` | ||
|
|
||
| This is setting the product reference of the product in the cart/order so there is a way to distinguish between products. This is hidden as it is not needed to be displayed to the user. | ||
|
|
||
|
|
||
| {% hint style="warning" %} | ||
|
|
||
| The `remove` button is added here but is not covered in this guide. This will be covered in a separate guide. | ||
|
|
||
| {% endhint %} | ||
|
|
||
| Finally a button is added to submit the form to update the cart. This will call the `UpdateCart` action in the `CartSurfaceController` which will then show a success message to the user. | ||
|
|
||
| ## Adding the Controller | ||
|
|
||
| Create a new Controller called `CartSurfaceController.cs` | ||
|
|
||
| {% hint style="warning" %} | ||
|
|
||
| The namespaces used in this Controller are important and need to be included. | ||
|
|
||
| using Microsoft.AspNetCore.Mvc; | ||
| using Umbraco.Cms.Core.Cache; | ||
| using Umbraco.Cms.Core.Logging; | ||
| using Umbraco.Cms.Core.Models.PublishedContent; | ||
| using Umbraco.Cms.Core.Routing; | ||
| using Umbraco.Cms.Core.Services; | ||
| using Umbraco.Cms.Core.Web; | ||
| using Umbraco.Cms.Infrastructure.Persistence; | ||
| using Umbraco.Cms.Web.Website.Controllers; | ||
| using Umbraco.Commerce.Common.Validation; | ||
| using Umbraco.Commerce.Core.Api; | ||
| using Umbraco.Commerce.Core.Models; | ||
| using Umbraco.Commerce.Extensions; | ||
| using Umbraco.Extensions; | ||
|
|
||
| {% endhint %} | ||
|
|
||
| ```csharp | ||
| public class CartSurfaceController : SurfaceController | ||
| { | ||
| public CartSurfaceController(IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IPublishedUrlProvider publishedUrlProvider, IUmbracoCommerceApi commerceApi) : base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider) | ||
| { | ||
| _commerceApi = commerceApi; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| The equivalent code for having this as a Primary Constructor | ||
|
|
||
| ```csharp | ||
| public class CartSurfaceController(IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IPublishedUrlProvider publishedUrlProvider, IUmbracoCommerceApi commerceApi) : SurfaceController(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider) | ||
| { | ||
| } | ||
| ``` | ||
|
|
||
|
|
||
|
|
||
| The `CartDto` is a class that is used to pass data to the Controller. This is a simple class that has a property for the `productReference` and an array of `OrderLineQuantityDto[]`. | ||
|
|
||
| ```csharp | ||
| public class CartDto | ||
| { | ||
| public string ProductReference { get; set; } | ||
| public OrderLineQuantityDto[] OrderLines { get; set; } | ||
| } | ||
|
|
||
| public class OrderLineQuantityDto | ||
| { | ||
| public Guid Id { get; set; } | ||
| public decimal Quantity { get; set; } | ||
| } | ||
| ``` | ||
|
|
||
| {% hint style="warning" %} | ||
| `ProductReference` is not used here but a simple example of how you could pass the product reference to the controller for other similar related tasks. | ||
| {% endhint %} | ||
|
|
||
| We now need to add the `Action` in order to update the items in the cart. This will be called when the button is clicked. | ||
|
|
||
| ```csharp | ||
| [HttpPost] | ||
| public IActionResult UpdateCart(CartDto cart) | ||
| { | ||
| try | ||
| { | ||
| _commerceApi.Uow.Execute(uow => | ||
| { | ||
| var store = CurrentPage?.Value<StoreReadOnly>("store", fallback: Fallback.ToAncestors); | ||
|
|
||
| if (store == null) return; | ||
|
|
||
| var order = _commerceApi.GetCurrentOrder(store.Id) | ||
| .AsWritable(uow); | ||
|
|
||
| foreach (var orderLine in cart.OrderLines) | ||
| { | ||
| order.WithOrderLine(orderLine.Id) | ||
| .SetQuantity(orderLine.Quantity); | ||
| } | ||
|
|
||
| _commerceApi.SaveOrder(order); | ||
|
|
||
| uow.Complete(); | ||
| }); | ||
| } | ||
| catch (ValidationException) | ||
| { | ||
| ModelState.AddModelError(string.Empty, "Failed to update cart"); | ||
|
|
||
| return CurrentUmbracoPage(); | ||
| } | ||
|
|
||
| TempData["SuccessMessage"] = "Cart updated"; | ||
|
|
||
| return RedirectToCurrentUmbracoPage(); | ||
| } | ||
| ``` | ||
|
|
||
| - A `try catch` block is used to capture any validation errors that may occur when updating items in the cart. | ||
| - `store` variable is used to access the store to retrieve the store ID. | ||
| - `order` is used to retrieve the current order. In the Commerce Api everything is read-only for performance so we need to make it writable in order to add the product. | ||
| - We loop through all the `orderLines(items)` in the cart and set the new quantity amount which was set in the View and passed into the CartDto model. | ||
| - `SaveOrder` is called to save the order. | ||
| - If there are any validation errors, they are added to ModelState error and the user is redirected back to the current page. | ||
| - `TempData` is used to store a message to be displayed to the user if the product has been succesfully updated. | ||
|
|
||
| {% hint style="warning" %} | ||
| Umbraco Commerce uses the Unit of Work pattern in order to complete saving the item (uow.Complete). When retrieving or saving data ideally you would want the entire transaction to be committed however if there is an error then nothing is changed on the database. | ||
| {% endhint %} | ||
|
|
||
| If you have followed the 'Add item to cart' article then run the application, add an item to your cart and navigate to your cart.cshtml page. Enter a new quantity click the Update Cart button and the item(s) in your cart would confirm the values have been updated with a success message. | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.