Table of Contents

Manage addresses

Manage user addresses in frontend

The Users - Manage Addresses app renders a frontend address book for the current user. It can list only the user’s own addresses or include addresses from other users who share the same customer number (when allowed). Editors can optionally enable create/edit/delete of the addresses.

Note

Template locations:

  • List template: /Templates/Users/UserAddresses/List
  • Edit template: /Templates/Users/UserAddresses/Edit

What the app does

When the app runs on a paragraph it either shows a list view or an edit view depending on the request:

  • ?Cmd=EditAddress&AddressId={id} (GET): will render the edit template for the selected address, or a blank form when AddressId=0
  • POST commands when editing is allowed:
    • ?Cmd=SaveAddress&AddressId={id}: create or update the address, then redirect back without the Cmd/AddressId query
    • ?Cmd=DeleteAddress&AddressId={id}: delete the address, then redirect back
    • ?Cmd=SetDefault&AddressId={id}: set the address as default for its kind and clear any previous default in the same scope

The list template receives an AddressListViewModel (with the page of addresses and paging metadata). The edit template receives a UserAddressViewModel with:

  • Address – the editable AddressViewModel (name, address lines, zip, city, country/code, phone, email, kind, is default, etc.)
  • Result – the outcome of the most recent operation (None, Success, InvalidEmail)

Paragraph app settings

Manage addresses

From the paragraph app you have these settings:

  • Templates
    • List addresses template: choose a Razor template from /Templates/Users/UserAddresses/List
    • Edit address template: choose a Razor template from /Templates/Users/UserAddresses/Edit
  • Display
    • Addresses per page (PageSize)
    • Sort by (Id, Name, Address, Country, CustomerNumber)
    • Sort direction
    • Source: own addresses or own addresses and addresses of users with same customer number
    • Allow user to edit addresses: enables create, edit, delete, and set default

List template

Place a .cshtml file in /Templates/Users/UserAddresses/List. The template should inherit ViewModelTemplate<AddressListViewModel> and import the Dynamicweb.Users.Frontend.UserAddresses namespace (for the helper links).

Minimal example

@inherits ViewModelTemplate<Dynamicweb.Frontend.AddressListViewModel>
@using Dynamicweb
@using Dynamicweb.Rendering
@using Dynamicweb.Users.Frontend.UserAddresses


<!-- Create a link to create a new address -->
@{
  var newAddress = Model.GetCreateNewAddressLink(Pageview.Page.ID); // /?ID=..&Cmd=EditAddress&AddressId=0
}

<div class="actions">
  @if (Model.AllowEditAddress) { <a href="@newAddress" class="btn">New address</a> }
</div>

@if (Model.Addresses?.Any() == true) {
  <table class="table">
    <thead>
      <tr>
        <th>Name</th>
        <th>Address</th>
        <th>Zip &amp; City</th>
        <th>Default</th>
        <th></th>
      </tr>
    </thead>
    <tbody>
      @foreach (var a in Model.Addresses) {
      <!-- Create edit and delete links with the AddressID parameter of the specific address -->
        var editLink = Model.GetAddressLink(Pageview.Page.ID, a.Id);
        var deleteLink = Model.GetDeleteAddressLink(Pageview.Page.ID, a.Id);
        <tr>
          <td>@a.Name</td>
          <td>@a.Address @a.HouseNumber</td>
          <td>@a.Zip @a.City</td>
          <td>@(a.IsDefault ? "Default" : "")</td>
          <td>
            <a href="@editLink">Edit</a>
            @if (Model.AllowEditAddress) {
              <form method="post" action="@deleteLink" class="inline" onsubmit="return confirm('Delete this address?');">
                <button type="submit" class="link">Delete</button>
              </form>
            }
          </td>
        </tr>
      }
    </tbody>
  </table>
} else {
  <p>No addresses found.</p>
}

<!-- Render simple paging if available (example assumes PageNum in query) -->
@if (Model.PageCount > 1) {
  <nav class="pagination">
    Page @Model.PageNumber of @Model.PageCount
  </nav>
}

Edit template

Place a .cshtml file in /Templates/Users/UserAddresses/Edit. The template should inherit ViewModelTemplate<UserAddressViewModel> and import the Dynamicweb.Users.Frontend.UserAddresses namespace. When the edit template is loaded with an AddressId parameter it will show the correlating address. If no AddressId is present, a new address is created.

Minimal example

@inherits ViewModelTemplate<Dynamicweb.Users.Frontend.UserAddresses.UserAddressViewModel>
@using Dynamicweb
@using Dynamicweb.Rendering
@using Dynamicweb.Users.Frontend.UserAddresses

@{
  <!-- Display the correct title depending on the Id -->
  var title = Model.Address.Id == 0 ? "New address" : "Edit address";

  <!-- Create the links for saving or deleting an address or make an address default -->
  var saveAction = Model.GetSaveAddressLink(Pageview.Page.ID);
  var deleteAction = Model.GetDeleteAddressLink(Pageview.Page.ID);
  var setDefault = Model.SetDefaultAddressLink(Pageview.Page.ID);
}

<h2>@title</h2>

<form method="post" action="@saveAction">
  <div class="grid">
    <div class="form-control">
      <label for="Name">Name</label>
      <input type="text" id="Name" name="Name" value="@Model.Address.Name" required />
    </div>
    <div class="form-control">
      <label for="Address">Address</label>
      <input type="text" id="Address" name="Address" value="@Model.Address.Address" required />
    </div>
    <div class="form-control">
      <label for="HouseNumber">House number</label>
      <input type="text" id="HouseNumber" name="HouseNumber" value="@Model.Address.HouseNumber" />
    </div>
    <div class="form-control">
      <label for="Zip">Zip code</label>
      <input type="text" id="Zip" name="Zip" value="@Model.Address.Zip" required />
    </div>
    <div class="form-control">
      <label for="City">City</label>
      <input type="text" id="City" name="City" value="@Model.Address.City" required />
    </div>
    <div class="form-control">
      <label for="CountryCode">Country</label>
      <input type="text" id="CountryCode" name="CountryCode" value="@Model.Address.CountryCode" />
    </div>

    <div class="form-control">
      <label>
        <input type="checkbox" id="IsDefault" name="IsDefault" @(Model.Address.IsDefault ? "checked" : "") />
        Default address
      </label>
    </div>
  </div>

  <div class="actions">
    <button type="submit" id="SaveAddressButton">Save</button>
    @if (Model.Address.Id > 0) {
      <form method="post" action="@setDefault" class="inline">
        <button type="submit">Set as default</button>
      </form>
    }
  </div>

  @if (Model.Result != Dynamicweb.Users.Frontend.UserAddresses.UserAddressResultType.None) {
    <p class="form-message">@Translate(Model.Result.ToString())</p>
  }
</form>

<!-- Delete Address Form -->
@if (Model.Address.Id > 0) {
  <form method="post" action="@deleteAction" onsubmit="return confirm('Delete this address?');">
    <button type="submit" class="btn btn-danger" id="DeleteUserButton">Delete</button>
  </form>
}

Handling results in your template

Use Model.Result to surface success or validation feedback.

@switch (Model.Result)
{
  case Dynamicweb.Users.Frontend.UserAddresses.UserAddressResultType.None:
    break;
  case Dynamicweb.Users.Frontend.UserAddresses.UserAddressResultType.Success:
    <div class="success">Your address has been saved.</div>
    break;
  case Dynamicweb.Users.Frontend.UserAddresses.UserAddressResultType.InvalidEmail:
    <div class="error">Please enter a valid email address for the address record.</div>
    break;
}

How commands, scope & redirects work

  • Scope (which addresses are visible/editable):
    • Own addresses: only addresses belonging to the current user.
    • Same customer number: includes active users who share the current user’s CustomerNumber.
    • A user can only modify/delete an address they own or one belonging to a user with the same CustomerNumber (when that source is enabled).
  • Default address logic: When setting an address to default, the module first clears any existing default for the same address kind within the chosen scope (own user or same customer number) and then saves the new default.
  • Redirects: After save/delete/set‑default, the app redirects back to the same page without the Cmd/AddressId query so the next GET can show the latest state and a clean URL.
To top