编辑产品类似于添加新产品,现在让我们看看如何编辑产品: ## 定义应用接口 让我们从为`IProductAppService`接口定义两个新方法: ``` Task<ProductDto> GetAsync(Guid id); Task UpdateAsync(Guid id, CreateUpdateProductDto input); ``` 第一种方法用于通过ID获取产品。我们在`UpdateAsync`方法中重用之前定义的`CreateUpdateProductDto`。 ## 实现应用接口 实现这些新方法非常简单。将以下方法添加到`ProductAppService`类中: ``` public async Task<ProductDto> GetAsync(Guid id) {     return ObjectMapper.Map<Product, ProductDto>(         await _productRepository.GetAsync(id)     ); } public async Task UpdateAsync(Guid id, CreateUpdateProductDto input) {     var product = await _productRepository.GetAsync(id);     ObjectMapper.Map(input, product); } ``` `GetAsync`方法用于从数据库中获取产品,并将其映射到`ProductDto`对象后进行返回。`UpdateAsync`方法获取到一个产品后,将给定的DTO输入映射到产品。通过这种方式,我们用新值覆盖产品。 对于这个例子,我们不需要调用`_productRepository.UpdateAsync`,因为 EF Core有一个变更跟踪系统。ABP 的**工作单元**如果没有抛出异常,则在请求结束时会自动保存更改。我们将在\[*第 6 章*\] \*使用数据访问基础架构”\*中介绍工作单元系统。 应用层已完成。接下来,我们将创建一个产品编辑 UI。 ## 用户界面 创建一个`EditProductModal.cshtml`Razor 页面(*ProductManagement.Web项目的* *Pages/Products*文件夹下)。打开`EditProductModal.cshtml.cs`,代码更改如下: ``` using System; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using ProductManagement.Products; namespace ProductManagement.Web.Pages.Products {     public class EditProductModalModel : ProductManagementPageModel     {         [HiddenInput]         [BindProperty(SupportsGet = true)]         public Guid Id { get; set; }         [BindProperty]         public CreateEditProductViewModel Product { get; set; }         public SelectListItem[] Categories { get; set; }         private readonly IProductAppService _productAppService;         public EditProductModalModel(IProductAppService productAppService)         {             _productAppService = productAppService;         }         public async Task OnGetAsync()         {             // TODO         }         public async Task<IActionResult> OnPostAsync()         {             // TODO         }     } } ``` 表单中`Id`字段将被隐藏。 它还应该支持 HTTP GET 请求,因为 GET 请求会打开此模型,并且我们需要产品 ID 来编辑表单。 `Product`和`Categories`属性类似于创建产品。 我们还将`IProductAppService`接口注入到构造函数。 我们实现`OnGetAsync`方法,如下代码块所示: ``` public async Task OnGetAsync() {     var productDto = await _productAppService.GetAsync(Id);     Product = ObjectMapper.Map<ProductDto, CreateEditProductViewModel>(productDto);          var categoryLookup = await _productAppService.GetCategoriesAsync();     Categories = categoryLookup.Items         .Select(x => new SelectListItem(x.Name, x.Id.ToString()))         .ToArray(); } ``` 首先,我们要先获取一个产品 ( `ProductDto`),再将其转换为`CreateEditProductViewModel`,使用它在 UI 上来创建编辑表单。然后,我们在表单上选择产品类别。 因为这里映射了`ProductDto`到`CreateEditProductViewModel`,所以我们需要在`ProductManagementWebAutoMapperProfile`类中定义配置映射([*ProductManagement.Web*](http://ProductManagement.Web)项目中),这和我们之前操作是一样的: ``` CreateMap<ProductDto, CreateEditProductViewModel>(); ``` 我们再看下`OnPostAsync()`方法: ``` public async Task<IActionResult> OnPostAsync() {     await _productAppService.UpdateAsync(Id,         ObjectMapper.Map<CreateEditProductViewModel,                             CreateUpdateProductDto>(Product)     );     return NoContent(); } ``` `OnPostAsync`方法很简单,把`CreateEditProductViewModel`转换为`CreateUpdateProductDto`。 接着,我们切换到`EditProductModal.cshtml`,内容更改如下: ``` @page @using Microsoft.AspNetCore.Mvc.Localization @using ProductManagement.Localization @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @model ProductManagement.Web.Pages.Products.EditProductModalModel @inject IHtmlLocalizer<ProductManagementResource> L @{     Layout = null; } <abp-dynamic-form abp-model="Product" asp-page="/Products/EditProductModal">     <abp-modal>         <abp-modal-header title="@Model.Product.Name"></abp-modal-header>         <abp-modal-body>             <abp-input asp-for="Id" />             <abp-form-content/>         </abp-modal-body>         <abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>     </abp-modal> </abp-dynamic-form> ``` 页面与`CreateProductModal.cshtml`非常相似。我刚刚将`Id`字段作为隐藏字段添加到表单,用来存储`Id`编辑的产品的属性。 最后,我们可以添加一个**编辑**按钮以从产品列表中打开编辑模态窗口。打开`Index.cshtml.js`文件,并在`dataTable`代码的头部添加一个`ModalManager`对象: ``` var editModal = new abp.ModalManager(abp.appPath + 'Products/EditProductModal'); ``` 然后,在`dataTable`内部的`columnDefs`数组中定义一个列(第一项): ``` {     title: l('Actions'),     rowAction: {         items:             [                 {                     text: l('Edit'),                     action: function (data) {                         editModal.open({ id: data.record.id });                     }                 }             ]     } }, ``` 此代码向数据表添加了一个新的**Actions**列,并添加了一个**Edit**操作按钮,单击即可打开编辑窗口。`rowAction`是 ABP Framework 提供的一个特殊选项。它用于在表中的一行添加一个或多个操作按钮。 最后,在`dataTable`初始化代码后添加如下: ``` editModal.onResult(function () {     dataTable.ajax.reload(); }); ``` 在保存产品编辑对话框后刷新数据表,确保我们可以看到表上的最新数据。最终的 UI 类似于下图: ![](https://img.kancloud.cn/29/82/2982358d4679a7eb3964b8ec6990e1db_1116x664.png) 我们现在可以查看、创建和编辑产品了。最后一部分将实现删除产品。