Skip to content

Commit 22b9bb4

Browse files
committed
Added articles
1 parent dbb7090 commit 22b9bb4

File tree

10 files changed

+1196
-2
lines changed

10 files changed

+1196
-2
lines changed

14/umbraco-commerce/SUMMARY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
* [Configure SQLite support](how-to-guides/configure-sqlite-support.md)
3434
* [Limit Order Line Quantity](how-to-guides/limit-orderline-quantity.md)
3535
* [Use an Alternative Database for Umbraco Commerce Tables](how-to-guides/use-an-alternative-database-for-umbraco-commerce-tables.md)
36+
* [Add item to Cart](how-to-guides/add-item.md)
37+
* [Update Cart](how-to-guides/update-cart.md)
38+
* [Delete item in Cart](how-to-guides/delete-item.md)
3639

3740
## Key Concepts
3841

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
---
2+
description: How-To Guide to add an item to your cart.
3+
---
4+
5+
# Add item to Cart
6+
7+
To add an item to the cart, configure Umbraco with a store and add the necessary properties for interaction. Learn more by following the [Getting started with Umbraco Commerce: The Backoffice tutorial](../tutorials/getting-started-with-commerce).
8+
9+
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.
10+
11+
Create a new Document Type with the template. Call it **Product Page** with the following property aliases: `productTitle`, `productDescription`, `price`, `stock`.
12+
13+
The following property editors are recommeded to be used for the above:
14+
15+
* `productTitle`: TextString
16+
* `productDescription`: TextArea
17+
* `price`: Umbraco Commerce Price
18+
* `stock`: Umbraco Commerce Stock
19+
20+
The Product Page template can be implemented as shown below.
21+
22+
```csharp
23+
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ProductPage>
24+
@{
25+
var store = Model.Value<StoreReadOnly>("store", fallback: Fallback.ToAncestors);
26+
var product = CommerceApi.Instance.GetProduct(store.Id, Model.Key.ToString(), "en-GB");
27+
var price = product.TryCalculatePrice().ResultOrThrow("Unable to calculate product price");
28+
}
29+
```
30+
31+
The code above does the following:
32+
33+
- 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.
34+
- 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.
35+
- 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.
36+
- Finally, you need to calculate the price which is then displayed without VAT. This can also be displayed with VAT.
37+
38+
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:
39+
40+
```csharp
41+
@using (Html.BeginUmbracoForm("AddToCart", "CartSurface"))
42+
{
43+
@Html.Hidden("productReference", Model.Key.ToString())
44+
<h1>@Model.Value<string>("productTitle")</h1>
45+
<h2>@Model.Value<string>("productDescription")</h2>
46+
47+
<p>Our price excluding VAT <strong>@price.WithoutTax.ToString("C0") </strong></p>
48+
49+
if (@Model.Value<int>("stock") == 0)
50+
{
51+
<p>Sorry, out of stock</p>
52+
}
53+
else
54+
{
55+
<button type="submit">Add to Basket</button>
56+
}
57+
58+
}
59+
```
60+
61+
The hidden field uses the `productReference` to be passed across to the Controller.
62+
63+
## Adding the Controller
64+
65+
For the button to work, you need to implement a controller. An example of this is shown below.
66+
67+
Create a new Controller called `CartSurfaceController.cs`.
68+
69+
{% hint style="warning" %}
70+
71+
The namespaces used in this Controller are important and need to be included.
72+
73+
```
74+
using Microsoft.AspNetCore.Mvc;
75+
using Umbraco.Cms.Core.Cache;
76+
using Umbraco.Cms.Core.Logging;
77+
using Umbraco.Cms.Core.Models.PublishedContent;
78+
using Umbraco.Cms.Core.Routing;
79+
using Umbraco.Cms.Core.Services;
80+
using Umbraco.Cms.Core.Web;
81+
using Umbraco.Cms.Infrastructure.Persistence;
82+
using Umbraco.Cms.Web.Website.Controllers;
83+
using Umbraco.Commerce.Common.Validation;
84+
using Umbraco.Commerce.Core.Api;
85+
using Umbraco.Commerce.Core.Models;
86+
using Umbraco.Commerce.Extensions;
87+
using Umbraco.Extensions;
88+
```
89+
90+
{% endhint %}
91+
92+
```csharp
93+
public class CartSurfaceController : SurfaceController
94+
{
95+
public CartSurfaceController(IUmbracoContextAccessor umbracoContextAccessor,
96+
IUmbracoDatabaseFactory databaseFactory,
97+
ServiceContext services, AppCaches appCaches,
98+
IProfilingLogger profilingLogger,
99+
IPublishedUrlProvider publishedUrlProvider,
100+
IUmbracoCommerceApi commerceApi)
101+
: base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
102+
{
103+
_commerceApi = commerceApi;
104+
}
105+
}
106+
```
107+
108+
Below you can see the equivalent code for having this as a Primary Constructor:
109+
110+
```csharp
111+
public class CartSurfaceController(IUmbracoContextAccessor umbracoContextAccessor,
112+
IUmbracoDatabaseFactory databaseFactory,
113+
ServiceContext services, AppCaches appCaches,
114+
IProfilingLogger profilingLogger,
115+
IPublishedUrlProvider publishedUrlProvider)
116+
: SurfaceController(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
117+
{
118+
}
119+
```
120+
121+
The CartDto class below is used to pass the `productReference` across to the Controller. This class has only one property for the `productReference`.
122+
123+
```csharp
124+
public class CartDto
125+
{
126+
public string ProductReference { get; set; }
127+
}
128+
```
129+
130+
We now need to add the Action to add the item to the cart. This action will be called when the button is clicked.
131+
132+
```csharp
133+
[HttpPost]
134+
public IActionResult AddToBasket(CartDto cart)
135+
{
136+
commerceApi.Uow.Execute(uow =>
137+
{
138+
var store = CurrentPage.Value<StoreReadOnly>("store", fallback: Fallback.ToAncestors);
139+
140+
if (store == null) return;
141+
142+
try
143+
{
144+
var order = commerceApi.GetOrCreateCurrentOrder(store.Id)
145+
.AsWritable(uow)
146+
.AddProduct(cart.ProductReference, 1);
147+
148+
commerceApi.SaveOrder(order);
149+
150+
uow.Complete();
151+
152+
TempData["SuccessFeedback"] = "Product added to cart";
153+
return RedirectToCurrentUmbracoPage();
154+
}
155+
catch (ValidationException ve)
156+
{
157+
throw new ValidationException(ve.Errors);
158+
}
159+
catch (Exception ex)
160+
{
161+
logger.Error(ex, "An error occurred.");
162+
}
163+
});
164+
}
165+
```
166+
167+
The code above does the following:
168+
169+
- The `store` variable is used to access the store to get the store ID.
170+
- A try-catch block captures any errors that may occur when adding the item to the cart, including any validation errors.
171+
- `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.
172+
- `AddProduct` is called and `productReference` is passed along with the quantity.
173+
- `SaveOrder` is called to save the order.
174+
- `TempData` stores a message to be displayed to the user if the product has been added to the cart.
175+
176+
{% hint style="warning" %}
177+
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.
178+
{% endhint %}
179+
180+
Finally, you need to add the `TempData` to tell the user that the product has been added to the cart.
181+
182+
## Add a partial view to display the message
183+
184+
Create a new partial view called `Feedback.cshtml`.
185+
186+
```csharp
187+
@Html.ValidationSummary(true, "", new { @class = "danger" })
188+
189+
@{
190+
var success = TempData["SuccessFeedback"]?.ToString();
191+
192+
if (!string.IsNullOrWhiteSpace(success))
193+
{
194+
<div class="success">@success</div>
195+
}
196+
}
197+
```
198+
199+
You can now run the application, click the button, and see the product added to the cart with a message displayed to the user.
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
---
2+
description: Learn how to remove items added to the shopping cart.
3+
---
4+
5+
# Delete item from cart
6+
7+
{% hint style="info" %}
8+
This guide builds on the guide on [update-cart.md). It is recommended to follow that guide before starting this one.
9+
{% endhint %}
10+
11+
This will teach you how to delete an item from the cart.
12+
13+
Your view for the `cart.cshtml` page will be similar the example below.
14+
15+
```csharp
16+
@inherits UmbracoViewPage
17+
@{
18+
var store = Model.Value<StoreReadOnly>("store", fallback: Fallback.ToAncestors);
19+
var currentOrder = CommerceApi.Instance.GetCurrentOrder(store!.Id);
20+
if (currentOrder == null) return;
21+
22+
@using (Html.BeginUmbracoForm("UpdateCart", "CartSurface"))
23+
{
24+
@foreach (var item in currentOrder.OrderLines.Select((ol, i) => new
25+
{
26+
OrderLine = ol,
27+
Index = i
28+
}))
29+
{
30+
<p>
31+
@Html.Hidden($"orderLines[{item.Index}].Id", item.OrderLine.Id)
32+
@item.OrderLine.Name @Html.Hidden($"orderLines[{item.Index}].Quantity", (int)item.OrderLine.Quantity, new { @type = "number" })
33+
@Html.Hidden($"orderLines[{item.Index}].ProductReference", item.OrderLine.ProductReference)
34+
<a href="@Url.SurfaceAction("RemoveFromCart", "CartSurface", new { OrderLineId = item.OrderLine.Id })">Remove Item</a>
35+
</p>
36+
37+
}
38+
39+
<button type="submit">Update Cart</button>
40+
41+
var success = TempData["SuccessMessage"]?.ToString();
42+
43+
if (!string.IsNullOrWhiteSpace(success))
44+
{
45+
<div class="success">@success</div>
46+
}
47+
}
48+
}
49+
```
50+
51+
The code below allows the Umbraco `SurfaceAction` to call `RemoveFromCart` when the link is clicked. It will also pass the `OrderLineId`.
52+
53+
```csharp
54+
<a href="@Url.SurfaceAction("RemoveFromCart", "BasketSurface", new { OrderLineId = item.OrderLine.Id })">Remove</a>
55+
```
56+
57+
## Adding the Controller
58+
59+
For the button to work, you need to add some functionality via a Controller.
60+
61+
Create a new Controller called `CartSurfaceController.cs`
62+
63+
{% hint style="warning" %}
64+
65+
The namespaces used in this Controller are important and need to be included.
66+
67+
```
68+
using Microsoft.AspNetCore.Mvc;
69+
using Umbraco.Cms.Core.Cache;
70+
using Umbraco.Cms.Core.Logging;
71+
using Umbraco.Cms.Core.Models.PublishedContent;
72+
using Umbraco.Cms.Core.Routing;
73+
using Umbraco.Cms.Core.Services;
74+
using Umbraco.Cms.Core.Web;
75+
using Umbraco.Cms.Infrastructure.Persistence;
76+
using Umbraco.Cms.Web.Website.Controllers;
77+
using Umbraco.Commerce.Common.Validation;
78+
using Umbraco.Commerce.Core.Api;
79+
using Umbraco.Commerce.Core.Models;
80+
using Umbraco.Commerce.Extensions;
81+
using Umbraco.Extensions;
82+
```
83+
84+
{% endhint %}
85+
86+
```csharp
87+
public class CartSurfaceController : SurfaceController
88+
{
89+
public CartSurfaceController(IUmbracoContextAccessor umbracoContextAccessor,
90+
IUmbracoDatabaseFactory databaseFactory,
91+
ServiceContext services,
92+
AppCaches appCaches,
93+
IProfilingLogger profilingLogger,
94+
IPublishedUrlProvider publishedUrlProvider,
95+
IUmbracoCommerceApi commerceApi)
96+
: base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
97+
{
98+
_commerceApi = commerceApi;
99+
}
100+
}
101+
```
102+
103+
The example below is the equivalent code for having this as a Primary Constructor:
104+
105+
```csharp
106+
public class CartSurfaceController(IUmbracoContextAccessor umbracoContextAccessor,
107+
IUmbracoDatabaseFactory databaseFactory,
108+
ServiceContext services,
109+
AppCaches appCaches,
110+
IProfilingLogger profilingLogger,
111+
IPublishedUrlProvider publishedUrlProvider,
112+
IUmbracoCommerceApi commerceApi)
113+
: SurfaceController(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
114+
{
115+
}
116+
```
117+
118+
119+
120+
The `CartDto` is a class used to pass data to the Controller. In this instance, it passes over the `OrderLineId`.
121+
122+
```csharp
123+
public class CartDto
124+
{
125+
public Guid OrderLineId { get; set; }
126+
}
127+
```
128+
129+
You need to add the `Action` to delete the item from the cart. This will be called when the button is clicked.
130+
131+
```csharp
132+
[HttpGet]
133+
public IActionResult RemoveFromCart(CartDto cart)
134+
{
135+
try
136+
{
137+
_commerceApi.Uow.Execute(uow =>
138+
{
139+
var store = CurrentPage?.Value<StoreReadOnly>("store", fallback: Fallback.ToAncestors);
140+
141+
if (store == null) return;
142+
143+
var order = _commerceApi.GetOrCreateCurrentOrder(store.Id)
144+
.AsWritable(uow)
145+
.RemoveOrderLine(cart.OrderLineId);
146+
147+
_commerceApi.SaveOrder(order);
148+
149+
uow.Complete();
150+
});
151+
}
152+
catch (ValidationException)
153+
{
154+
ModelState.AddModelError(string.Empty, "Failed to remove product from cart");
155+
156+
return CurrentUmbracoPage();
157+
}
158+
159+
TempData["SuccessMessage"] = "Item removed";
160+
161+
return RedirectToCurrentUmbracoPage();
162+
}
163+
```
164+
165+
- A `try-catch` block captures any validation errors that may occur when updating items in the cart.
166+
- The `store` variable is used to access the store to retrieve the store ID.
167+
- `order` is used to retrieve the current order. In the Commerce API, everything is read-only for performance so you need to make it writable to add the product.
168+
- `SaveOrder` is called to save the order.
169+
- If there are any validation errors, they are added to a `ModelState` error, and the user is redirected back to the current page.
170+
- `TempData` stores a message to be displayed to the user if the product has been successfully updated.
171+
172+
{% hint style="warning" %}
173+
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.
174+
{% endhint %}
175+
176+
If you have followed the [Add item to cart](add-item.md) article, run the application, add an item to your cart, and navigate to your `cart.cshtml` page. Clicking the `Remove Item` button will delete the item in your cart and display a message.

14/umbraco-commerce/how-to-guides/overview.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ In this section, we will provide a series of How-To Guides, showcasing how to pe
88

99
## Available guides
1010

11-
<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center">Migrate from Vendr to Umbraco Commerce</td><td><a href="migrate-from-vendr-to-umbraco-commerce/">migrate-from-vendr-to-umbraco-commerce</a></td></tr><tr><td align="center">Configure SQLite support</td><td><a href="configure-sqlite-support.md">configure-sqlite-support.md</a></td></tr><tr><td align="center">Limit Order Line Quantity</td><td><a href="limit-orderline-quantity.md">limit-orderline-quantity.md</a></td></tr><tr><td align="center">Add item to Cart</td><td><a href="add-item.md">add-item.md</a></td></tr><tr><td align="center">Use an alternative database for Umbraco Commerce tables</td><td><a href="use-an-alternative-database-for-umbraco-commerce-tables.md">use-an-alternative-database-for-umbraco-commerce-tables.md</a></td></tr></tbody></table>
11+
<table data-card-size="large" data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center">Migrate from Vendr to Umbraco Commerce</td><td><a href="migrate-from-vendr-to-umbraco-commerce/">migrate-from-vendr-to-umbraco-commerce</a></td></tr><tr><td align="center">Configure SQLite support</td><td><a href="configure-sqlite-support.md">configure-sqlite-support.md</a></td></tr><tr><td align="center">Add item to Cart</td><td><a href="add-item.md">add-item.md</a></td></tr><tr><td align="center">Update Cart</td><td><a href="update-cart.md">update-cart.md</a></td></tr>
12+
<tr><td align="center">Delete item from Cart</td><td><a href="delete-item.md">delete-item.md</a></td></tr><tr><td align="center">Limit Order Line Quantity</td><td><a href="limit-orderline-quantity.md">limit-orderline-quantity.md</a></td></tr><tr><td align="center">Use an alternative database for Umbraco Commerce tables</td><td><a href="use-an-alternative-database-for-umbraco-commerce-tables.md">use-an-alternative-database-for-umbraco-commerce-tables.md</a></td></tr></tbody></table>

0 commit comments

Comments
 (0)