search
HomeBackend DevelopmentC#.Net TutorialABP introductory series (6) - display layer to implement addition, deletion, modification and query

This chapter will realize the addition, deletion, modification and check of the presentation layer by improving the Controller, View and ViewModel. The final implementation effect is as follows:

ABP introductory series (6) - display layer to implement addition, deletion, modification and query

1. Define Controller

ABP integrates ASP.NET MVC Controllers by introducing Abp.Web.Mvc naming Space, create a Controller that inherits from AbpController, we can use the following powerful functions that ABP has attached to us:

Localization

Exception handling

Wrap the returned JsonResult

Audit log

Permission authentication ([AbpMvcAuthorize] feature)

Unit of work (not enabled by default, enabled by adding [UnitOfWork])

1, create TasksController inherits from AbpController

Injects dependencies on application services through the constructor.

[AbpMvcAuthorize]    public class TasksController : AbpController
    {        private readonly ITaskAppService _taskAppService;        
private readonly IUserAppService _userAppService;        
public TasksController(ITaskAppService taskAppService, IUserAppService userAppService)        
{
            _taskAppService = taskAppService;
            _userAppService = userAppService;
        }
}

2. Create a list display partial view (_List.cshtml)

In the partial view, we output the task list through loop traversal.

@model IEnumerable<LearningMpaAbp.Tasks.Dtos.TaskDto>
<div>
    <ul class="list-group">        @foreach (var task in Model)
        {
            <li class="list-group-item">
                <div class="btn-group pull-right">
                    <button type="button" class="btn btn-info" onclick="editTask(@task.Id);">Edit</button>
                    <button type="button" class="btn btn-success" onclick="deleteTask(@task.Id);">Delete</button>
                </div>

                <div class="media">
                    <a class="media-left" href="#">
                        <i class="fa @task.GetTaskLable() fa-3x"></i>
                    </a>
                    <div class="media-body">
                        <h4 id="task-Title">@task.Title</h4>
                        <p class="text-info">@task.AssignedPersonName</p>
                        <span class="text-muted">@task.CreationTime.ToString("yyyy-MM-dd HH:mm:ss")</span>
                    </div>
                </div>

            </li>
        }
    </ul>
</div>

ABP introductory series (6) - display layer to implement addition, deletion, modification and query

3. Create a new partial view (_CreateTask.cshtml)

For a good user experience, we use asynchronous loading to implement the task of creation.

1, introduce js files

Using asynchronous submission requires the introduction of jquery.validate.unobtrusive.min.js and jquery.unobtrusive-ajax.min.js, among which jquery.unobtrusive-ajax.min .js, you need to install Microsoft's Microsoft.jQuery.Unobtrusive.Ajax package through Nuget.
Then introduce it into the view through bundling. Open BundleConfig.cs under the App_Start folder and add the following code:

 bundles.Add(     new ScriptBundle("~/Bundles/unobtrusive/js")
         .Include(             
 "~/Scripts/jquery.validate.unobtrusive.min.js",             
 "~/Scripts/jquery.unobtrusive-ajax.min.js"
             )
     );

Find Views/Shared/_Layout.cshtml and add a js reference to the bundle.

@Scripts.Render("~/Bundles/vendor/js/bottom")
@Scripts.Render("~/Bundles/js")//在此处添加下面一行代码
@Scripts.Render("~/Bundles/unobtrusive/js")

2, create partial view

Bootstrap-Modal and Ajax.BeginForm are used. If you don’t know about this, you can refer to
How much do you know about Ajax.BeginForm()
Introduction to the usage of Bootstrap-Modal

The Partial View is bound to the CreateTaskInput model. The final _CreateTask.cshtml code is as follows:

@model LearningMpaAbp.Tasks.Dtos.CreateTaskInput@{    ViewBag.Title = "Create";
}
<div class="modal fade" id="add" tabindex="-1" role="dialog" aria-labelledby="createTask" data-backdrop="static">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
                <h4 id="Create-nbsp-Task">Create Task</h4>
            </div>
            <div class="modal-body" id="modalContent">                
@using (Ajax.BeginForm("Create", "Tasks", new AjaxOptions()
                {                    
UpdateTargetId = "taskList",                    
InsertionMode = InsertionMode.Replace,                    
OnBegin = "beginPost(&#39;#add&#39;)",                    
OnSuccess = "hideForm(&#39;#add&#39;)",                   
 OnFailure = "errorPost(xhr, status, error,&#39;#add&#39;)"
                }))
                {                   
  @Html.AntiForgeryToken()
                    <div class="form-horizontal">
                        <h4 id="Task">Task</h4>
                        <hr />                       
   @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                        <div class="form-group">                            
   @Html.LabelFor(model => model.AssignedPersonId, "AssignedPersonId", htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">                                
   @Html.DropDownList("AssignedPersonId", null, htmlAttributes: new { @class = "form-control" })                                
   @Html.ValidationMessageFor(model => model.AssignedPersonId, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">                            
   @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">                                
   @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } })                                
   @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">                            
   @Html.LabelFor(model => model.Description, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">                                
   @Html.EditorFor(model => model.Description, new { htmlAttributes = new { @class = "form-control" } })                                
   @Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
                            </div>
   
                        </div>

                        <div class="form-group">                            
   
                        @Html.LabelFor(model => model.State, htmlAttributes: new { 
   
                        @class = "control-label col-md-2" })
                            <div class="col-md-10">                                
   
                        @Html.EnumDropDownListFor(model => model.State, htmlAttributes: new { 
   
                        @class = "form-control" })                                
   
                        @Html.ValidationMessageFor(model => model.State, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            <div class="col-md-offset-2 col-md-10">
                                <button type="submit" class="btn btn-default">Create</button>
                            </div>
                        </div>
                    </div>
                }
            </div>
        </div>
    </div>
</div>

Corresponding Controller code:

[ChildActionOnly]public PartialViewResult Create(){    
var userList = _userAppService.GetUsers();
    ViewBag.AssignedPersonId = new SelectList(userList.Items, "Id", "Name");    
return PartialView("_CreateTask");
}

[HttpPost]
[ValidateAntiForgeryToken]public ActionResult Create(CreateTaskInput task){   
 var id = _taskAppService.CreateTask(task);    
 var input = new GetTasksInput();    
 var output = _taskAppService.GetTasks(input);    
 return PartialView("_List", output.Tasks);
}

4. Create and update the partial view (_EditTask.cshtml)

Similarly, this view also uses Asynchronous update method also uses Bootstrap-Modal and Ajax.BeginForm() technology. This Partial View is bound to the UpdateTaskInput model.

@model LearningMpaAbp.Tasks.Dtos.UpdateTaskInput@{    ViewBag.Title = "Edit";
}

<div class="modal fade" id="editTask" tabindex="-1" role="dialog" aria-labelledby="editTask" data-backdrop="static">

    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
                <h4 id="Edit-nbsp-Task">Edit Task</h4>
            </div>
            <div class="modal-body" id="modalContent">                
@using (Ajax.BeginForm("Edit", "Tasks", new AjaxOptions()
                {                    UpdateTargetId = "taskList",                    
InsertionMode = InsertionMode.Replace,                   
 OnBegin = "beginPost(&#39;#editTask&#39;)",                   
 OnSuccess = "hideForm(&#39;#editTask&#39;)"
                }))
                {                   
 @Html.AntiForgeryToken()

                    <div class="form-horizontal">
                        <h4 id="Task">Task</h4>
                        <hr />                        
 @Html.ValidationSummary(true, "", new { @class = "text-danger" })                        
 @Html.HiddenFor(model => model.Id)

                        <div class="form-group">                                
 @Html.LabelFor(model => model.AssignedPersonId, "AssignedPersonId", htmlAttributes: new { @class = "control-label col-md-2" })
                                <div class="col-md-10">                                    
 @Html.DropDownList("AssignedPersonId", null, htmlAttributes: new { @class = "form-control" })                                    
 @Html.ValidationMessageFor(model => model.AssignedPersonId, "", new { @class = "text-danger" })
                                </div>
                            </div>

                        <div class="form-group">                            
 @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">                                
 @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } })                                
 @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">                            
 @Html.LabelFor(model => model.Description, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">                                
 @Html.EditorFor(model => model.Description, new { htmlAttributes = new { @class = "form-control" } })                                
 @Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">                           
  @Html.LabelFor(model => model.State, htmlAttributes: new { @class = "control-label col-md-2" })
                            <div class="col-md-10">                                
  @Html.EnumDropDownListFor(model => model.State, htmlAttributes: new { @class = "form-control" })                                
  @Html.ValidationMessageFor(model => model.State, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group">
                            <div class="col-md-offset-2 col-md-10">
                                <input type="submit" value="Save" class="btn btn-default" />
                            </div>
                        </div>
                    </div>
                }

            </div>
        </div>
    </div>
</div>
<script type="text/javascript">    //该段代码十分重要,确保异步调用后jquery能正确执行验证逻辑
    $(function () {        //allow validation framework to parse DOM
        $.validator.unobtrusive.parse(&#39;form&#39;);
    });
</script>

Backend code:

public PartialViewResult Edit(int id){    var task = _taskAppService.GetTaskById(id);    
var updateTaskDto = AutoMapper.Mapper.Map<UpdateTaskInput>(task);    
var userList = _userAppService.GetUsers();
    ViewBag.AssignedPersonId = new SelectList(userList.Items, "Id", "Name", updateTaskDto.AssignedPersonId);    
return PartialView("_EditTask", updateTaskDto);
}

[HttpPost]
[ValidateAntiForgeryToken]public ActionResult Edit(UpdateTaskInput updateTaskDto){
    _taskAppService.UpdateTask(updateTaskDto);    
var input = new GetTasksInput();    
var output = _taskAppService.GetTasks(input);   
 return PartialView("_List", output.Tasks);
}

5. Create Index view

在首页中,我们一般会用来展示列表,并通过弹出模态框的方式来进行新增更新删除。为了使用ASP.NET MVC强视图带给我们的好处(模型绑定、输入校验等等),我们需要创建一个ViewModel来进行模型绑定。因为Abp提倡为每个不同的应用服务提供不同的Dto进行数据交互,新增对应CreateTaskInput,更新对应UpdateTaskInput,展示对应TaskDto。那我们创建的ViewModel就需要包含这几个模型,方可在一个视图中完成多个模型的绑定。

1,创建视图模型(IndexViewModel)

namespace LearningMpaAbp.Web.Models.Tasks{    public class IndexViewModel
    {        /// <summary>
        /// 用来进行绑定列表过滤状态
        /// </summary>
        public TaskState? SelectedTaskState { get; set; }        /// <summary>
        /// 列表展示
        /// </summary>
        public IReadOnlyList<TaskDto> Tasks { get; }        /// <summary>
        /// 创建任务模型
        /// </summary>
        public CreateTaskInput CreateTaskInput { get; set; }        /// <summary>
        /// 更新任务模型
        /// </summary>
        public UpdateTaskInput UpdateTaskInput { get; set; }        
public IndexViewModel(IReadOnlyList<TaskDto> items)        {
            Tasks = items;
        }        
        /// <summary>
        /// 用于过滤下拉框的绑定
        /// </summary>
        /// <returns></returns>

        public List<SelectListItem> GetTaskStateSelectListItems()        {            
var list=new List<SelectListItem>()
            {                new SelectListItem()
                {
                    Text = "AllTasks",
                    Value = "",
                    Selected = SelectedTaskState==null
                }
            };

            list.AddRange(Enum.GetValues(typeof(TaskState))
                .Cast<TaskState>()
                .Select(state=>new SelectListItem()
                {
                    Text = $"TaskState_{state}",
                    Value = state.ToString(),
                    Selected = state==SelectedTaskState
                })
            );            return list;
        }
    }
}

2,创建视图

Index视图,通过加载Partial View的形式,将列表、新增视图一次性加载进来。

@using Abp.Web.Mvc.Extensions
@model LearningMpaAbp.Web.Models.Tasks.IndexViewModel

@{
    ViewBag.Title = L("TaskList");
    ViewBag.ActiveMenu = "TaskList"; 
//Matches with the menu name in SimpleTaskAppNavigationProvider to highlight the menu item
}
@section scripts{
    @Html.IncludeScript("~/Views/Tasks/index.js");
}<h2>
    @L("TaskList")    
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#add">Create Task</button>

    <a class="btn btn-primary" data-toggle="modal" href="@Url.Action("RemoteCreate")" 
data-target="#modal" role="button">(Create Task)使用Remote方式调用Modal进行展现</a>

    <!--任务清单按照状态过滤的下拉框-->
    <span class="pull-right">
        @Html.DropDownListFor(
            model => model.SelectedTaskState,
            Model.GetTaskStateSelectListItems(),
            new
            {
                @class = "form-control select2",
                id = "TaskStateCombobox"
            })    </span></h2><!--任务清单展示--><div class="row" id="taskList">
    @{ Html.RenderPartial("_List", Model.Tasks); }</div><!--通过初始加载页面的时候提前将创建任务模态框加载进来-->
@Html.Action("Create")<!--编辑任务模态框通过ajax动态填充到此div中--><div id="edit"></div><!--Remote方式弹出创建任务模态框-->
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="createTask" data-backdrop="static">
    <div class="modal-dialog" role="document">
        <div class="modal-content">

        </div>
    </div></div>

3,Remote方式创建任务讲解

Remote方式就是,点击按钮的时候去加载创建任务的PartialView到指定的div中。而我们代码中另一种方式是通过@Html.Action("Create")的方式,在加载Index的视图的作为子视图同步加载了进来。
感兴趣的同学自行查看源码,不再讲解。

<a class="btn btn-primary" data-toggle="modal" href="@Url.Action("RemoteCreate")" 
data-target="#modal" role="button">(Create Task)使用Remote方式调用Modal进行展现</a>
<!--Remote方式弹出创建任务模态框-->
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="createTask" data-backdrop="static">
    <div class="modal-dialog" role="document">
        <div class="modal-content">

        </div>
    </div></div>

4,后台代码

  public ActionResult Index(GetTasksInput input)        {            
  var output = _taskAppService.GetTasks(input);            
  var model = new IndexViewModel(output.Tasks)
            {
                SelectedTaskState = input.State

            };            return View(model);
        }

5,js代码(index.js)

var taskService = abp.services.app.task;

(function ($) {

    $(function () {        var $taskStateCombobox = $(&#39;#TaskStateCombobox&#39;);

        $taskStateCombobox.change(function () {
            getTaskList();
        });        var $modal = $(".modal");        //显示modal时,光标显示在第一个输入框
        $modal.on(&#39;shown.bs.modal&#39;,            function () {
                $modal.find(&#39;input:not([type=hidden]):first&#39;).focus();
            });

    });
})(jQuery);//异步开始提交时,显示遮罩层function beginPost(modalId) {    var $modal = $(modalId);

    abp.ui.setBusy($modal);
}//异步开始提交结束后,隐藏遮罩层并清空Formfunction hideForm(modalId) {   
 var $modal = $(modalId);    
var $form = $modal.find("form");
    abp.ui.clearBusy($modal);
    $modal.modal("hide");    //创建成功后,要清空form表单
    $form[0].reset();
}//处理异步提交异常function errorPost(xhr, status, error, modalId) {    if (error.length>0) {
        abp.notify.error(&#39;Something is going wrong, please retry again later!&#39;);        
var $modal = $(modalId);
        abp.ui.clearBusy($modal);
    }
}function editTask(id) {
    abp.ajax({
        url: "/tasks/edit",
        data: { "id": id },
        type: "GET",
        dataType: "html"
    })
        .done(function (data) {
            $("#edit").html(data);
            $("#editTask").modal("show");
        })
        .fail(function (data) {
            abp.notify.error(&#39;Something is wrong!&#39;);
        });
}function deleteTask(id) {
    abp.message.confirm(        "是否删除Id为" + id + "的任务信息",        
function (isConfirmed) {            if (isConfirmed) {
                taskService.deleteTask(id)
                    .done(function () {
                        abp.notify.info("删除任务成功!");
                        getTaskList();
                    });
            }
        }
    );

}function getTaskList() {    var $taskStateCombobox = $(&#39;#TaskStateCombobox&#39;);    
var url = &#39;/Tasks/GetList?state=&#39; + $taskStateCombobox.val();
    abp.ajax({
        url: url,
        type: "GET",
        dataType: "html"
    })
        .done(function (data) {
            $("#taskList").html(data);
        });

js代码中处理了Ajax回调函数,以及任务状态过滤下拉框更新事件,编辑、删除任务代码。其中getTaskList()函数是用来异步属性列表,对应调用的GetList()Action的后台代码如下:

public PartialViewResult GetList(GetTasksInput input){    
var output = _taskAppService.GetTasks(input);    
return PartialView("_List", output.Tasks);
}

六、总结

至此,完成了任务的增删改查。展现层主要用到了Asp.net mvc的强类型视图、Bootstrap-Modal、Ajax异步提交技术。
其中需要注意的是,在异步加载表单时,需要添加以下js代码,jquery方能进行前端验证。

<script type="text/javascript">
    $(function () {        //allow validation framework to parse DOM
        $.validator.unobtrusive.parse(&#39;form&#39;);
    });

以上就是ABP入门系列(6)——展现层实现增删改查的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
C# .NET in the Modern World: Applications and IndustriesC# .NET in the Modern World: Applications and IndustriesMay 08, 2025 am 12:08 AM

C#.NET is widely used in the modern world in the fields of game development, financial services, the Internet of Things and cloud computing. 1) In game development, use C# to program through the Unity engine. 2) In the field of financial services, C#.NET is used to develop high-performance trading systems and data analysis tools. 3) In terms of IoT and cloud computing, C#.NET provides support through Azure services to develop device control logic and data processing.

C# .NET Framework vs. .NET Core/5/6: What's the Difference?C# .NET Framework vs. .NET Core/5/6: What's the Difference?May 07, 2025 am 12:06 AM

.NETFrameworkisWindows-centric,while.NETCore/5/6supportscross-platformdevelopment.1).NETFramework,since2002,isidealforWindowsapplicationsbutlimitedincross-platformcapabilities.2).NETCore,from2016,anditsevolutions(.NET5/6)offerbetterperformance,cross-

The Community of C# .NET Developers: Resources and SupportThe Community of C# .NET Developers: Resources and SupportMay 06, 2025 am 12:11 AM

The C#.NET developer community provides rich resources and support, including: 1. Microsoft's official documents, 2. Community forums such as StackOverflow and Reddit, and 3. Open source projects on GitHub. These resources help developers improve their programming skills from basic learning to advanced applications.

The C# .NET Advantage: Features, Benefits, and Use CasesThe C# .NET Advantage: Features, Benefits, and Use CasesMay 05, 2025 am 12:01 AM

The advantages of C#.NET include: 1) Language features, such as asynchronous programming simplifies development; 2) Performance and reliability, improving efficiency through JIT compilation and garbage collection mechanisms; 3) Cross-platform support, .NETCore expands application scenarios; 4) A wide range of practical applications, with outstanding performance from the Web to desktop and game development.

Is C# Always Associated with .NET? Exploring AlternativesIs C# Always Associated with .NET? Exploring AlternativesMay 04, 2025 am 12:06 AM

C# is not always tied to .NET. 1) C# can run in the Mono runtime environment and is suitable for Linux and macOS. 2) In the Unity game engine, C# is used for scripting and does not rely on the .NET framework. 3) C# can also be used for embedded system development, such as .NETMicroFramework.

The .NET Ecosystem: C#'s Role and BeyondThe .NET Ecosystem: C#'s Role and BeyondMay 03, 2025 am 12:04 AM

C# plays a core role in the .NET ecosystem and is the preferred language for developers. 1) C# provides efficient and easy-to-use programming methods, combining the advantages of C, C and Java. 2) Execute through .NET runtime (CLR) to ensure efficient cross-platform operation. 3) C# supports basic to advanced usage, such as LINQ and asynchronous programming. 4) Optimization and best practices include using StringBuilder and asynchronous programming to improve performance and maintainability.

C# as a .NET Language: The Foundation of the EcosystemC# as a .NET Language: The Foundation of the EcosystemMay 02, 2025 am 12:01 AM

C# is a programming language released by Microsoft in 2000, aiming to combine the power of C and the simplicity of Java. 1.C# is a type-safe, object-oriented programming language that supports encapsulation, inheritance and polymorphism. 2. The compilation process of C# converts the code into an intermediate language (IL), and then compiles it into machine code execution in the .NET runtime environment (CLR). 3. The basic usage of C# includes variable declarations, control flows and function definitions, while advanced usages cover asynchronous programming, LINQ and delegates, etc. 4. Common errors include type mismatch and null reference exceptions, which can be debugged through debugger, exception handling and logging. 5. Performance optimization suggestions include the use of LINQ, asynchronous programming, and improving code readability.

C# vs. .NET: Clarifying the Key Differences and SimilaritiesC# vs. .NET: Clarifying the Key Differences and SimilaritiesMay 01, 2025 am 12:12 AM

C# is a programming language, while .NET is a software framework. 1.C# is developed by Microsoft and is suitable for multi-platform development. 2..NET provides class libraries and runtime environments, and supports multilingual. The two work together to build modern applications.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools