-
Notifications
You must be signed in to change notification settings - Fork 813
Create add-item article #6521
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 add-item article #6521
Changes from 11 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
3ec8908
Create add-item article
mr-shellychauhan 43c323a
Update 13/umbraco-commerce/how-to-guides/add-item
mr-shellychauhan db7a256
Update 13/umbraco-commerce/how-to-guides/add-item
mr-shellychauhan 2ca5381
Update 13/umbraco-commerce/how-to-guides/add-item
mr-shellychauhan dbe586a
Update 13/umbraco-commerce/how-to-guides/add-item
mr-shellychauhan f575d89
Update 13/umbraco-commerce/how-to-guides/add-item
mr-shellychauhan 71e4a92
Update 13/umbraco-commerce/how-to-guides/add-item
mr-shellychauhan a9deb42
Update 13/umbraco-commerce/how-to-guides/add-item
mr-shellychauhan c13ad58
Update 13/umbraco-commerce/how-to-guides/add-item
mr-shellychauhan aeca817
Update add-item
mr-shellychauhan e20da06
Corrected grammar and added more context
sofietoft 440a328
Update and rename add-item to add-item.md
mr-shellychauhan ed383f4
Fixed long sentence
sofietoft 70bfb75
Add article to SUMMARY.md
sofietoft 97436f6
Update SUMMARY.md
mr-shellychauhan 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,192 @@ | ||
| --- | ||
| description: How-To Guide to add an item to your cart. | ||
| --- | ||
|
|
||
| # Add item to Cart | ||
|
|
||
| To add an item to the cart, you need to set up Umbraco with a store and add the relevant properties to allow the store to interact with Umbraco. Learn more by following the [Getting started with Umbraco Commerce: The Backoffice tutorial](../tutorials/getting-started-with-commerce). | ||
|
|
||
| You will need the front end to be set up to allow an item to be added to the cart. This can be done by adding a button to the front end to call the Action to add the item to the cart. | ||
|
|
||
| Create a new Document Type with the template. Call it **Product Page** with the following property aliases: `productTitle`, `productDescription`, `price`, `stock`. | ||
|
|
||
| The Product Page template can be implemented as shown below. | ||
|
|
||
| ```csharp | ||
mr-shellychauhan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ProductPage> | ||
| @{ | ||
| var store = Model.Value<StoreReadOnly>("store", fallback: Fallback.ToAncestors); | ||
| var product = CommerceApi.Instance.GetProduct(store.Id, Model.Key.ToString(), "en-GB"); | ||
| var price = product.TryCalculatePrice().ResultOrThrow("Unable to calculate product price"); | ||
| } | ||
| ``` | ||
|
|
||
| The code above does the following: | ||
|
|
||
| - You need to access the store to access the relevant properties for your product, such as price. The store has a fallback property allowing you to traverse the tree to find the store. | ||
| - You retrieve the product based on the store and a reference for the product. The 'productReference' comes from the Model which is a single product. | ||
| - The Product is returned as a ProductSnapshot which is Umbraco Commerce obtaining the page ID and carrying out necessary processes to bring in the data for further processing. | ||
| - Finally, you need to calculate the price which is then displayed without VAT. This can also be displayed with VAT. | ||
|
|
||
| To display this you need to add some markup or at least amend it to include a button to add an item. Add the following to the same file: | ||
|
|
||
| ```csharp | ||
| @using (Html.BeginUmbracoForm("AddToCart", "CartSurface")) | ||
| { | ||
| @Html.Hidden("productReference", Model.Key.ToString()) | ||
| <h1>@Model.Value<string>("productTitle")</h1> | ||
| <h2>@Model.Value<string>("productDescription")</h2> | ||
|
|
||
| <p>Our price excluding VAT <strong>@price.WithoutTax.ToString("C0") </strong></p> | ||
|
|
||
| if (@Model.Value<int>("stock") == 0) | ||
| { | ||
| <p>Sorry, out of stock</p> | ||
| } | ||
| else | ||
| { | ||
| <button type="submit">Add to Basket</button> | ||
| } | ||
|
|
||
| } | ||
| ``` | ||
|
|
||
| The hidden field uses the `productReference` to be passed across to the Controller. | ||
|
|
||
| ## Adding the Controller | ||
|
|
||
| For the button to work, you need to implement a controller. An example of this is shown below. | ||
|
|
||
| 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; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Below you can see 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) | ||
| : SurfaceController(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider) | ||
| { | ||
| } | ||
| ``` | ||
|
|
||
| The CartDto class below is used to pass the `productReference` across to the Controller. This class has only one property for the `productReference`. | ||
|
|
||
| ```csharp | ||
| public class CartDto | ||
| { | ||
| public string ProductReference { get; set; } | ||
| } | ||
| ``` | ||
|
|
||
| We now need to add the Action to add the item to the cart. This action will be called when the button is clicked. | ||
|
|
||
| ```csharp | ||
| [HttpPost] | ||
| public IActionResult AddToBasket(CartDto cart) | ||
| { | ||
| commerceApi.Uow.Execute(uow => | ||
| { | ||
| var store = CurrentPage.Value<StoreReadOnly>("store", fallback: Fallback.ToAncestors); | ||
|
|
||
| if (store == null) return; | ||
|
|
||
| try | ||
| { | ||
| var order = commerceApi.GetOrCreateCurrentOrder(store.Id) | ||
| .AsWritable(uow) | ||
| .AddProduct(cart.ProductReference, 1); | ||
|
|
||
| commerceApi.SaveOrder(order); | ||
|
|
||
| uow.Complete(); | ||
|
|
||
| TempData["SuccessFeedback"] = "Product added to cart"; | ||
| return RedirectToCurrentUmbracoPage(); | ||
| } | ||
| catch (ValidationException ve) | ||
| { | ||
| throw new ValidationException(ve.Errors); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| logger.Error(ex, "An error occurred."); | ||
| } | ||
| }); | ||
| } | ||
| ``` | ||
|
|
||
| The code above does the following: | ||
|
|
||
| - The `store` variable is used to access the store to get the store ID. | ||
| - A try-catch block captures any errors that may occur when adding the item to the cart, including any validation errors. | ||
| - `order` is used to retrieve the current order if one exists or create a new order against the store found. In the Commerce API, everything is read-only for performance so you need to make it writable to add the product. | ||
| - `AddProduct` is called and `productReference` is passed along with the quantity. | ||
| - `SaveOrder` is called to save the order. | ||
| - `TempData` stores a message to be displayed to the user if the product has been added to the cart. | ||
|
|
||
| {% hint style="warning" %} | ||
| Umbraco Commerce uses the Unit of Work pattern 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 nothing is changed on the database. | ||
| {% endhint %} | ||
|
|
||
| Finally, you need to add the `TempData` to tell the user that the product has been added to the cart. | ||
|
|
||
| ## Add a partial view to display the message | ||
|
|
||
| Create a new partial view called `Feedback.cshtml`. | ||
|
|
||
| ```csharp | ||
| @Html.ValidationSummary(true, "", new { @class = "danger" }) | ||
|
|
||
| @{ | ||
| var success = TempData["SuccessFeedback"]?.ToString(); | ||
|
|
||
| if (!string.IsNullOrWhiteSpace(success)) | ||
| { | ||
| <div class="success">@success</div> | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| You can now run the application, click the button, and see the product added to the cart with a message displayed to the user. | ||
Oops, something went wrong.
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.