65.9K
CodeProject 正在变化。 阅读更多。
Home

WCF RESTful 服务和 ASP.NET MVC 5 中的 WebGrid - 第 2 部分

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (20投票s)

2014 年 6 月 21 日

CPOL

7分钟阅读

viewsIcon

65493

downloadIcon

2427

在本文中,我们将学习如何创建 WCF RESTful 服务,并在 ASP.NET MVC 5 应用程序中使用 WebGrid 控件来消耗这些服务。

注意:要使用此处附加的代码,必须运行在第一部分创建的 WCF 服务。

引言

这是文章的第二部分,共两部分。在第一部分中,我们创建了 WCF RESTful 服务,将在本部分中使用。在本第二部分中,我们将创建一个带有 WebGrid 控件的 ASP.NET MVC Web 应用程序,并执行 CRUD 操作。

如果您尚未阅读第一部分,我建议您先访问那里,因为它将为您提供更好的背景信息,并在您阅读本文时提供帮助。以下是本文第二部分的概述:

  • 创建 ASP.NET MVC 5 应用程序
  • 在 WebGrid 控件中显示数据
  • 添加内联编辑操作
  • 添加内联删除操作
  • 添加创建操作

创建 ASP.NET MVC 5 应用程序

除了本文,我们还将创建一个演示 MVC 应用程序,该应用程序将对客户数据执行 CRUD 操作。客户数据将显示在 WebGrid 中,用户将在其中执行创建、读取、更新(编辑)和删除操作。当用户在客户端(浏览器)执行任何操作时,调用将转到 MVC 应用程序 Controller 的特定 Action 方法。然后 Action 方法将调用第一部分中创建的 WCF RESTful Web 服务。最后,WCF Web 服务会调用存储库以对数据库执行适当的操作来持久化更改。

请按照以下步骤创建演示应用程序:

  1. 让我们开始创建一个示例应用程序,选择 ASP.NET Web 应用程序模板,将项目命名为 DemoMVCApp,然后单击“确定”。

    Project Template
     
  2. 现在,选择 MVC 模板,如下所示,然后单击“确定”。

    MVC Selected

    Visual Studio 将为我们创建一个 ASP.NET MVC 项目结构。我们将在接下来的步骤中修改它以实现所需的功能。
     
  3. 在 Models 文件夹下,添加一个名为 Customer 的类,并在其中写入以下代码,如下所示:
        public class Customer
        {
            public int CustomerId { get; set; }
            [Required]
            [DisplayName("Name")]
            public string CustomerName { get; set; }
            
            [Required]
            [DisplayName("Address")]        
            public string CustomerAddress { get; set; }
        }
     }
    
  4. Controller 文件夹下,添加一个名为 CustomerController 的控制器。此控制器将具有 Customer 模型的 Get、Post、Put 和 Delete 操作的方法。在 CustomerController 类中,写入以下代码:
    readonly string customerServiceUri = "https://:1750/CustomerService.svc/";
    // customerServiceUri is a global variable for this customercontroller, having the path of CustomerService. 
    // Please change URI path if service is hosed at some different URI in your case. 
            public ActionResult Index()
            {
                List<Customer> customerList = new List<Customer>();
                using (WebClient webClient = new WebClient())
                {
                    string dwml;
                    dwml = webClient.DownloadString(customerUri + "GetAllCustomers");
                    customerList = JsonConvert.DeserializeObjectAsync<List<Customer>>(dwml).Result;
                }
                return View(customerList);
            }
    
    我们刚刚实现了一个名为 Index 的 Action 方法,该方法调用 WCF 服务,反序列化接收到的数据,并返回客户列表。
     

在 WebGrid 控件中显示数据

  1. 通过右键单击 CustomerController 中的 Index 方法并将其命名为 Index 来添加视图。它将在 Views > Customer 文件夹下添加一个 Index.cshtml 文件。在 Index 视图中写入以下代码。此代码将创建一个 WebGrid,并将数据绑定到该网格。我们直接引用脚本和 CSS 文件。(此处我们不关注打包和最小化功能。)

    注意:所有自定义 CSS 都写在 Content 文件夹下的 index.css 文件中,自定义脚本写在 Scripts 文件夹下的 index.js 文件中。请在相应的文件夹中创建这些文件,相应地编写代码,并在 Index 页面中进行引用。警告:将 index.js 的引用放在页面末尾。
    @model  IEnumerable<DemoMVCWebApp.Models.Customer>
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <link href="~/Content/index.css" rel="stylesheet" />
    @{
        var grid = new WebGrid(Model, canPage: true, rowsPerPage: 5,
        selectionFieldName: "selectedRow");
        grid.Pager(WebGridPagerModes.NextPrevious);}
    <div id="gridContent">
        @grid.GetHtml(tableStyle: "webGrid",
                headerStyle: "header",
                alternatingRowStyle: "alt",
                selectedRowStyle: "select",
                rowStyle: "webgrid-row-style",
                columns: grid.Columns(
                grid.Column("CustomerId", "Customer Id", @<text> <span id="spnCustomerId">@item.CustomerId</span></text>,
                           canSort: false),
                grid.Column("CustomerName", "Customer Name", format: @<text>
                                     <span id="spnCustomerName" class="display-mode">@item.CustomerName</span>
                                     <input type="text" id="CustomerName" value="@item.CustomerName" class="edit-mode"/></text>,
                           canSort: false),
                           
                grid.Column("CustomerAddress", "Customer Address", format: @<text>
                                     <span id="spnCustomerAddress" class="display-mode">@item.CustomerAddress</span>
                                     <input type="text" id="CustomerAddress" value="@item.CustomerAddress" class="edit-mode"/></text>,
                           canSort: false),
                grid.Column("Action", format: @<text>
                                    <img src="~/Content/images/edit.jpg" title="Edit Customer" id="btnEdit" class="edit-button"/>
                                    <img src="~/Content/images/delete.jpg" title="Delete Customer" class="delete-customer"/>
                                     </text>, style: "width:220px", canSort: false)
                          ))
    </div>
    
  2. App_Start 文件夹下的 RoutConfig.cs 文件中,按如下方式设置默认路由:
    defaults: new { controller = "Customer", action = "Index", id = UrlParameter.Optional }
    
  3. 运行应用程序,希望您能在 WebGrid 中看到所有客户,如下所示:

    Output for Customer page
     

添加内联编辑操作

要编辑任何客户,我们将使用 WebGrid 中的内联编辑。正如您在 WebGrid 的第四列中看到的,我们使用图像 - 一个用于编辑,另一个用于删除操作。

在本节中,我们将编写一些代码,以便在单击编辑图像时,相应行中的数据可以进行编辑。同时,编辑图像将出现在相同位置,并显示保存图像和适当的工具提示。因此,编辑功能如下所示:

Project Template

单击保存图像时,编辑后的客户对象将进入 CustomerControllerEditCustomer Action 方法。然后该 Action 方法将调用 WCF 服务,服务将使用存储库将更新后的客户保存在数据库中。

从编程角度来看,WebGrid 中的每一行都有一个 span 标签和一个带有不同 CSS 类的 input 标签。页面加载时,所有带有 CSS 类“edit-mode”的文本框都将隐藏。我们还考虑到一次应该只有一个行可编辑。为了实现内联编辑,我们在单击编辑按钮时切换 CSS 类,因为现在 span 标签应该被隐藏,而文本框应该出现在相应的行中。

如果编辑功能还不清楚,请运行应用程序并查看编辑按钮的行为,然后查看 index.js 文件中编写的 JavaScript 代码。或者,您可以继续按照以下步骤操作,随着代码的输入和理解,事情会变得显而易见。

  1. 打开 Scripts 文件夹下的 index.js 文件,并写入以下代码。此代码会在页面加载时隐藏不需要在查看模式下使用的输入框(带有 CSS 类“edit-mode”)。
    $(document).ready(function () {
    $('.edit-mode').hide();
    });
    
  2. 此外,我们需要编写 JavaScript 来处理单击编辑按钮的事件。在 index.js 中写入以下代码。希望代码中的注释足以解释它。
                    $('.edit-button').on("click", function () {
        // allEditableRow : will have all rows which are editable (where save button is visible).
        var allEditableRow = $("[src='/Content/images/save.jpg']");
        
        // make row editable only if no other row is editable as of now by toggle
        // otherwise go to else and save data of editable row first or alert to save that"
        if (allEditableRow.length == 0) {
            var tr = $(this).parents('tr:first');
            tr.find('.edit-mode,.display-mode').toggle();
            var imageSource = $(this).attr('src');
            if (imageSource == '/Content/images/edit.jpg') {
                $(this).attr('src', '/Content/images/save.jpg');
                $(this).attr('title', 'Save Customer');
            }
        }
        else {
            // making sure that only one row is editable and save button of editable row is clicked
            if (allEditableRow.length == 1 && $(this).attr('src') == '/Content/images/save.jpg')
            {
                          
                var selectedId = $(this).parents('tr').find('td:nth-child(1)').text().trim();
                var selectedName = $(this).parents('tr').find('#CustomerName').val();
                var selectedAddless = $(this).parents('tr').find('#CustomerAddress').val();
                // create object with updated values
                var customerModel =
                    {
                        "CustomerId": selectedId,
                        "CustomerName": selectedName,
                        "CustomerAddress": selectedAddless
                    };
                $.ajax({
                    url: '/Customer/EditCustomer',
                    type: 'POST',
                    contentType: 'application/json; charset=utf-8',
                    data: JSON.stringify(customerModel)
                });
                alert("Your data is saved");
                window.location.reload(true);
                $(this).attr('src', '/Content/images/edit.jpg');
            }
            else {
                alert("Please finish the editing of current editable row. Save first");
            }
        }
    
  3. CustomerController 中,我们需要实现 EditCustomer Action 方法,如下所示:
    public void EditCustomer(Customer customer)
            {
                using (WebClient wc = new WebClient())
                {
                    MemoryStream ms = new MemoryStream();
                    DataContractJsonSerializer serializerToUplaod = new DataContractJsonSerializer(typeof(Customer));
                    serializerToUplaod.WriteObject(ms, customer);
                    wc.Headers["Content-type"] = "application/json";
                    wc.UploadData(customerServiceUri + "EditCustomer", "PUT", ms.ToArray());
                }
            }
    
  4. 运行应用程序,编辑任何客户,然后保存它,更新的数据将保存在数据库中,并在 WebGrid 中反映出来。

添加内联删除操作

要删除记录,用户将单击相应行中的删除图像。用户将收到一个确认弹出窗口。如果用户确认删除,则相应的行数据将被删除。删除按钮单击时的确认弹出窗口如下屏幕截图所示。

Delete Operation

我们将编写删除功能的代码。

  1. 打开 Scripts 文件夹下的 index.js 文件,并写入以下代码:
    $('.delete-customer').click(function () {
        var selectedId = $(this).parents('tr').find('td:nth-child(1)').text().trim();
        var selectedName = $(this).parents('tr').find('#CustomerName').val();
        var message = "Please confirm delete for Customer ID " + selectedId + ", and Name: " + selectedName + " ? \nClick 'OK' to delete otherwise 'Cancel'.";
        if (confirm(message) == true) {
            selectedId = $(this).parents('tr:first').children('td:first').text();
            $.ajax({
                url: '/Customer/DeleteCustomer',
                data: { id: selectedId },
                type: 'POST',
                success: function () {
                    window.location.reload();
                },
                error: function (xhr) {
                    alert("something seems wrong");
                }
            });
        }
        else
        {
            alert("Delete is Canceled!");
        }
    });
    
  2. CustomerController 类中写入以下代码。此 Action 方法将用于删除操作。
    public void DeleteCustomer(int id)
            {
                using (WebClient wc = new WebClient())
                {
                    MemoryStream ms = new MemoryStream();
                    DataContractJsonSerializer serializerToUplaod = new DataContractJsonSerializer(typeof(Customer));
                    serializerToUplaod.WriteObject(ms, id);
                    wc.Headers["Content-type"] = "application/json";
                    wc.UploadData(customerServiceUri + "DeleteCustomer", "DELETE", ms.ToArray());
                }
            }
    
  3. 运行应用程序,尝试从 WebGrid 中删除任何记录,它应该按预期工作。

添加创建操作

为了实现此功能,我们将使用部分视图。当用户单击“新建客户”按钮时,AJAX 调用会转到 CustomerControllerGetCustomerPV Action 方法,并获取部分视图。将出现一个表单,用户将填写数据并单击表单内的“保存”按钮。然后调用将转到 CustomerControllerCreateCustomer Action 方法来保存新客户。我们在此处没有使用广泛的验证,但两个字段都是必填项。如果单击保存按钮而不填写任何数据,则会显示错误消息,如下面的屏幕截图所示。

HTML Layout of Views

让我们按照以下步骤来实现此功能:

  1. CustomerController 中写入以下代码行:
    public ActionResult GetCustomerPV()
            {
                return PartialView("CreateCustomerPV");
            }
    
  2. 通过右键单击 GetCustomerPV Action 方法并将其命名为 CreateCustomerPV 来创建一个部分视图。打开新创建的 CreateCustomerPV 部分视图并写入以下代码:
    @model DemoMVCWebApp.Models.Customer
    @*Below scripts files are used to provide the client side validation*@
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
    <div class="createDiv">
        <h4>Please fill below Customer Form:</h4>
        <br />
        @using (Html.BeginForm("CreateCustomer", "Customer"))
        {
            @Html.AntiForgeryToken()
            <div class="form-horizontal">
                @Html.ValidationSummary(true)
                <div class="form-group">
                    @Html.LabelFor(model => model.CustomerName, new { @class = "control-label col-md-2" })
                    <div class="col-md-10">
                        @Html.EditorFor(model => model.CustomerName)
                        @Html.ValidationMessageFor(model => model.CustomerName)
                    </div>
                </div>
                <div class="form-group">
                    @Html.LabelFor(model => model.CustomerAddress, new { @class = "control-label col-md-2" })
                    <div class="col-md-10">
                        @Html.EditorFor(model => model.CustomerAddress)
                        @Html.ValidationMessageFor(model => model.CustomerAddress)
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <input type="submit" value="Save" class="btnCustomerPV" />
                    </div>
                </div>
            </div>
        }
    </div>
    
  3. 现在,我们需要在主页面上添加一个名为“新建客户”的按钮,单击该按钮将调用部分视图。在 Index.cshtml 文件(Index 视图)中,将以下代码添加到 div 标签的正下方。我们添加了一个“div”标签,部分视图将添加到其中。
    <input type="button" value="New Customer" class="btnCustomerPV" />
    <div id="placeHolderCustomerPV">
    </div>
    
    现在打开 index.js 文件,并添加以下代码行,这将调用 GetCustomerPV Action 方法:
    $('.btnCustomerPV').click(function () {
        $('.btnCustomerPV').hide();
        $.ajax({
            // Call CreatePartialView action method
            url: '/Customer/GetCustomerPV',
            type: 'Get',
            success: function (data) {
                $("#placeHolderCustomerPV").empty().append(data);
            },
            error: function () {
                alert("something seems wrong");
            }
        });
    });
    
  4. 我们在部分视图中编写了以下代码,因此在单击部分视图的提交按钮时,调用将进入 CustomerControllerCreateCustomer Action 方法。
    @using (Html.BeginForm("CreateCustomer", "Customer"))
    
    在控制器中写入以下代码行以添加 CreateCustomer Action 方法:
    public ActionResult CreateCustomer(Customer customer)
            {
                using (WebClient wc = new WebClient())
                {
                    MemoryStream ms = new MemoryStream();
                    DataContractJsonSerializer serializerToUplaod = new DataContractJsonSerializer(typeof(Customer));
                    serializerToUplaod.WriteObject(ms, customer);
                    wc.Headers["Content-type"] = "application/json";
                    wc.UploadData(customerServiceUri + "AddCustomer", "POST", ms.ToArray());
                }
                int pageToShow;
                int totalCustomers;
                List<Customer> customerList = new List<Customer>();
                using (WebClient webClient = new WebClient())
                {
                    string customerCount;
                    customerCount = webClient.DownloadString(customerServiceUri + "GetCustomersCount");
                    totalCustomers = Convert.ToInt32(customerCount);
                }
                if (totalCustomers % 5 != 0)
                    pageToShow = (totalCustomers / 5) + 1;
                else pageToShow = totalCustomers / 5;
              
                return Redirect(HttpRuntime.AppDomainAppVirtualPath + "?page=" + pageToShow);
            }
    
    在此,在保存新客户后,我们将重定向到适当的索引以显示最近添加的数据。
     
  5. 现在运行应用程序,单击“新建客户”按钮,在表单中填写数据,然后单击“保存”按钮。数据将被保存,并且由于我们编写了重定向逻辑,它将显示在 WebGrid 控件的最后一行。

结论

希望您已享受我们在两篇文章中创建的演示,并学习了如何创建 WCF RESTful 服务及其在 ASP.NET MVC 应用程序中使用 WebGrid 控件的消耗。您的评论和建议非常欢迎。谢谢。

© . All rights reserved.