前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[ASP.NET MVC] 利用动态注入HTML的方式来设计复杂页面

[ASP.NET MVC] 利用动态注入HTML的方式来设计复杂页面

作者头像
蒋金楠
发布2022-05-09 13:07:22
3.5K0
发布2022-05-09 13:07:22
举报
文章被收录于专栏:大内老A

随着最终用户对用户体验需求的不断提高,实际上我们很多情况下已经在按照桌面应用的标准来设计Web应用,甚至很多Web页面本身就体现为一个单一的页面。对于这种复杂的页面,我们在设计的时候不可以真的将所有涉及的元素通通至于某个单独的View中,将复杂页面相对独立的内容“分而治之”才是设计之道。我们可以借鉴Smart Clent应用的设计方式:将一个Windows Form作为应用的容器(Smart Client Shell),在操作过程中动态地激活相应的用户控件(Smart Part)并加载到容器中。对于一个复杂页面来说,我们也只需要将其设计成一个容器,至于运行过程中动态显示的内容则可以通过Ajax调用获取相应的HTML来填充。[源代码从这里下载]

目录 一、实例演示 二、作为容器的View 三、显示联系人列表 四、弹出“修改联系人”对话框 五、联系人信息的最终修改

一、实例演示

我们先来演示一个简单的例子,假设我们要设计一个“联系人”管理的页面。该页面初始状态如左图所示,它仅仅具有一个用于输入查询条件(First Name和Last Name)进行联系人查询的表单。当用户输入相应的查询条件之后点击“Retrieve”按钮,相应的联系人列表显示以表格的形式显示出来(中图)。当我们点击作为ID的链接后,会以“模态对话框”的形式显示当前联系人的编辑“窗口”(右图)。

这个“单页面应用”是通过ASP.NET MVC开发的,接下来我们来逐步介绍如果将同一页面中的这三块不同的内容提取出来进行“分而治之”。

二、作为容器的View

如下所示的是表示联系人的Contact类型的定义,没有什么特别之处:

代码语言:javascript
复制
1: public class Contact

       2: {

       3:     [Required]

       4:     public string Id { get; set; }

       5:     [Required]

       6:     public string FirstName { get; set; }

       7:     [Required]

       8:     public string LastName { get; set; }

       9:     [Required]

      10:     [DataType(DataType.EmailAddress)]

      11:     public string EmailAddress { get; set; }

      12:     [Required]

      13:     [DataType(DataType.PhoneNumber)]

      14:     public string PhoneNo { get; set; }

      15: }

联系人管理对应的HomeController定义如下。简单起见,我们通过一个静态字段来表示维护的联系人列表。我们仅仅列出了默认的Action方法Index,它会直接将作为“容器页面”的View呈现出来。

代码语言:javascript
复制
1: public class HomeController : Controller

       2: {

       3:     private static List<Contact> contacts = new List<Contact>

       4:     {

       5:         new Contact{Id = "001", FirstName = "San", LastName = "Zhang", EmailAddress = "zhangsan@gmail.com", PhoneNo="123"},

       6:         new Contact{Id = "002", FirstName = "Si", LastName = "Li", EmailAddress = "zhangsan@gmail.com", PhoneNo="456"}

       7:     };

       8:  

       9:     public ActionResult Index()

      10:     {

      11:         return View();

      12:     }    

      13:      //其他Action方法

      14: }

如下所示的是Index.cshtml的定义,在这里使用了Twitter的Bootstrap,所示我们引用了相应的CSS和JS。这个主体部分包含三个<div>,分别对应着上述的三个部分。

代码语言:javascript
复制
1: <html>

       2:     <head>

       3:         <title>Contacts</title>

       4:         <link href="@Url.Content("~/Assets/css/bootstrap.css")" rel="stylesheet" type="text/css" />

       5:         <link href="@Url.Content("~/Assets/css/bootstrap-responsive.css")" rel="stylesheet" type="text/css" />

       6:     </head>

       7:     <body>

       8:         <div class="form-search">

       9:            @Html.Partial("QueryFormPartial")

      10:          </div>

      11:         <div id="contactList"></div>

      12:         <div class="modal fade" id="contactDialog"></div>

      13:  

      14:         <script type="text/javascript" src="@Url.Content("~/Assets/js/jquery-1.7.1.min.js")"></script>

      15:         <script type="text/javascript" src="@Url.Content("~/Assets/js/bootstrap.min.js")"></script>

      16:         <script type="text/javascript" src="@Url.Content("~/Assets/js/jquery.unobtrusive-ajax.min.js")"></script>

      17:         <script type="text/javascript" src="@Url.Content("~/Assets/js/jquery.validate.min.js")"></script>

      18:         <script type="text/javascript" src="@Url.Content("~/Assets/js/jquery.validate.unobtrusive.min.js")"></script>

      19:     </body>

      20: </html>

表示“查询表单”的部分定义在如下所示的Partial View(QueryFormPartial.cshtml),直接通过调用HtmlHelper的Partial方法呈现在当前View中。

代码语言:javascript
复制
1: @{

       2:     Layout = null; 

       3: }

       4: using (Ajax.BeginForm("Find", new AjaxOptions { OnSuccess = "renderCustomerList" }))

       5: { 

       6:    <fieldset>

       7:        <legend>Maintain Contacts</legend>

       8:        <label class="control-label" for="firstName">First Name. :</label>

       9:        <input type="text" name="firstName" class="input-medium search-query" />

      10:        <label class="control-label" for="lastName">Last Name :</label>

      11:        <input type="text" name="lastName" class="input-medium search-query" />

      12:        <input type="submit" value="Retrieve" class="btn btn-primary" />

      13:    </fieldset>

      14: }

三、显示联系人列表

QueryFormPartial.cshtml定义了一个以Ajax方式提交的表单,目标Action为具有如下定义的Find,它根据指定的First Name和Last Name筛选匹配的联系人列表,并将其呈现在一个名为ContactListPartial的View中。

代码语言:javascript
复制
1: public class HomeController : Controller

       2: {

       3:     //其他成员

       4:     public ActionResult Find(string firstName = "", string lastName = "")

       5:     { 

       6:         var result = from contact in contacts

       7:                         where (string.IsNullOrEmpty(firstName) || contact.FirstName.ToLower().Contains(firstName.ToLower()))

       8:                             &&(string.IsNullOrEmpty(lastName) || contact.LastName.ToLower().Contains(lastName.ToLower()))

       9:                         orderby contact.Id

      10:                         select contact;

      11:         return View("ContactListPartial",result.ToArray());

      12:     }

      13: }

如下所示的ContactListPartial.cshtml的定义,这是一个Model类型为IEnumerable<Contact>的强类型View,它以表格的形式将联系人列表呈现出来。

代码语言:javascript
复制
1: @model IEnumerable<Contact>

       2: @{

       3:     Layout = null;    

       4: }

       5: <table class="table table-striped table-bordered">

       6:     <thead>    

       7:         <tr>

       8:             <th>ID</th>

       9:             <th>First Name</th>

      10:             <th>Last Name</th>

      11:             <th>Email Address</th>

      12:             <th>Phone No.</th>

      13:         </tr>        

      14:     </thead>

      15:     <tbody>

      16:         @foreach (var contact in Model)

      17:         { 

      18:             <tr>

      19:                 <td>@Ajax.ActionLink(contact.Id, "Update", new { contactId = contact.Id }, new AjaxOptions { OnSuccess = "showDialog" , HttpMethod="GET"})</td>

      20:                 <td>@contact.FirstName</td>

      21:                 <td>@contact.LastName</td>

      22:                 <td>@contact.EmailAddress</td>

      23:                 <td>@contact.PhoneNo</td>               

      24:             </tr>

      25:         }

      26:     </tbody>

      27: </table>

从QueryFormPartial.cshtml的定义可以看到,表单成功提交之后会调用一个名为renderCustomerList的JavaScript函数(@using (Ajax.BeginForm("Find", new AjaxOptions { OnSuccess = "renderCustomerList" }))),它以如下的方式定义在Index.cshtml中。从定义了看出,它将获取的数据(实际上ContactListPartial这个View最终的HTML)作为contactList这个<div>的HTML。

代码语言:javascript
复制
1: <html>

       2:     <head>

       3:         <script type="text/javascript">   1:     2:             function renderCustomerList(data) {   3:                 $("#contactList").html(data);   4:             }   5:         </script>

       4:     </head>

       5: </html>

四、弹出“修改联系人”对话框

从ContactListPartial.cshtml的定义可以看到联系人ID以一个链接的方式呈现出来,点击该链接会以Ajax的方式访问Action方法Update,当前联系人ID会作为请求的参数(<td>@Ajax.ActionLink(contact.Id, "Update", new { contactId = contact.Id }, new AjaxOptions { OnSuccess = "showDialog" , HttpMethod="GET"})</td>)。如下所示的是Action方法Update的定义,它根据指定的ID获取对应的联系人,并将其呈现在一个名为ContactPartial 的View中。

代码语言:javascript
复制
1: public class HomeController : Controller

       2: {

       3:      //其他成员

       4:     [HttpGet]

       5:     public ActionResult Update(string contactId)

       6:     {

       7:         Contact contact = contacts.First(c => c.Id == contactId);

       8:         return View("ContactPartial", contact);

       9:     }

      10: }

如下所示的ContactPartial.cshtml的定义,这是一个Model类型为Contact的强类型View,它将联系人信息呈现在一个表单中。

代码语言:javascript
复制
1: @model Contact

       2: @{

       3:     Layout = null;

       4: }

       5: @using(Ajax.BeginForm("Update", null, new AjaxOptions { HttpMethod = "Post", OnSuccess = "reLoad" }, new { @class = "form-horizontal" }))

       6: {

       7:     <div class="modal-header">     

       8:     <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>

       9:     <h3>Contact Information</h3>

      10:     </div>

      11:     <div class="modal-body">

      12:         <div class="control-group">

      13:             @Html.HiddenFor(model=>model.Id)

      14:             @Html.LabelFor(model=>model.FirstName,new{@class="control-label"})

      15:             <div class="controls">

      16:                 @Html.EditorFor(model => model.FirstName)

      17:                 @Html.ValidationMessageFor(model => model.FirstName)

      18:             </div>

      19:         </div>

      20:         <div class="control-group">

      21:             @Html.LabelFor(model=>model.LastName,new{@class="control-label"})

      22:             <div class="controls">

      23:                 @Html.EditorFor(model => model.LastName)

      24:                 @Html.ValidationMessageFor(model => model.LastName)

      25:             </div>

      26:         </div>

      27:         <div class="control-group">

      28:             @Html.LabelFor(model => model.EmailAddress, new { @class = "control-label" })

      29:             <div class="controls">

      30:                 @Html.EditorFor(model => model.EmailAddress)                

      31:                 @Html.ValidationMessageFor(model => model.EmailAddress)

      32:             </div>

      33:         </div>

      34:         <div class="control-group">

      35:             @Html.LabelFor(model => model.PhoneNo, new { @class = "control-label" })

      36:             <div class="controls">

      37:                 @Html.EditorFor(model => model.PhoneNo)                

      38:                 @Html.ValidationMessageFor(model => model.PhoneNo)

      39:             </div>

      40:         </div>

      41:     </div>

      42:     <div class="modal-footer">

      43:     <a href="#" class="btn" data-dismiss="modal">Close</a>

      44:     <input type="submit" class="btn btn-primary" value="Save" />

      45:     </div>

      46: }

联系人编译窗口的弹出最终通过调用JavaScript函数showDialog实现(<td>@Ajax.ActionLink(contact.Id, "Update", new { contactId = contact.Id }, new AjaxOptions { OnSuccess = "showDialog" , HttpMethod="GET"})</td>),具体定义如下所示。它将获取到的数据(实际上是ContactPartial这个View最终的HTML)作为第三个<div>的HTML,并按照Bootstrap的方式以模态对话框的形式将其呈现出来。至于中间的两行代码,在于解决动态添加表单无法实施验证的问题。

代码语言:javascript
复制
1: <html>

       2:     <head>

       3:         <script type="text/javascript">   1:               2:             function showDialog(data) {   3:                 $("#contactDialog").html(data);   4:                 $("#contactDialog form")   5:                     .removeData("validator")   6:                     .removeData("unobtrusiveValidation");   7:                 $.validator.unobtrusive.parse($("#contactDialog form"));   8:                 $("#contactDialog").modal();   9:             }              10:         </script>

       4:     </head>

       5: </html>

五、联系人信息的最终修改

通过ContactPartial.cshtml的定义可以看出编辑联系人表单最终以POST的方式提交到HomeController的Action方法Update(@using(Ajax.BeginForm("Update", null, new AjaxOptions { HttpMethod = "Post", OnSuccess = "reLoad" }, new { @class = "form-horizontal" }))),该Action方法具有如下的定义。它在完成修改之后,返回字符串“OK”表明联系人修改成功。

代码语言:javascript
复制
1: public class HomeController : Controller

       2: {

       3:     //其他成员

       4:     [HttpPost]

       5:     public string  Update(Contact contact)

       6:     {

       7:         contacts.Remove(contacts.First(c=>c.Id == contact.Id));

       8:         contacts.Add(contact);

       9:         return "OK";

      10:     }

      11: }

联系人修改表单提交后关闭当前窗口并加载新的数据通过具有如下定义JavaScript函数Reload实现(@using(Ajax.BeginForm("Update", null, new AjaxOptions { HttpMethod = "Post", OnSuccess = "reLoad" }, new { @class = "form-horizontal" }))),该函数依然定义在Index.cshtml中。

代码语言:javascript
复制
1: <html>

       2:     <head>

       3:         <script type="text/javascript">   1:     2:             function reLoad(data) {   3:                 if (data == "OK") {   4:                     $("#contactDialog").modal("hide");   5:                     $(".form-search form").submit();   6:                 }   7:             }   8:         </script>

       4:     </head>

       5: </html>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2012-11-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、实例演示
  • 二、作为容器的View
  • 三、显示联系人列表
  • 四、弹出“修改联系人”对话框
  • 五、联系人信息的最终修改
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档