One ASP.NET 偷偷一瞥:优雅的Web Form,却是地狱的雪球

[原文发表地址] One ASP.NET Sneak Peek: Elegant Web Forms and Snowballs in Hell

[原文发表时间] 2012-02-01 01: 17 AM

大多数情况下,我是一名 ASP.NET开发人员。我不需要指定 MVC 或 Web Form,因为One ASP.NET是所有的核心。我的应用程序往往是混合的,不仅包括Web FormMVC还包括SignalR和 Web API。

Web Form通常因为大的View State,怪异的标记,被人所挑剔,或许人们不喜欢其控件模型。但是,Web Form也有它的地位,并正随着NET 4.5变得更好。这里是Damian Edwards的一些很酷的想法,先睹为快吧,这个团队一直致力于下一个版本的 ASP.NET.

作为一个开始的地方,请记住,ASP.NET路由起于 MVC ,并被移入到核心的 ASP.NET中。路由在所有的 ASP.NET应用程序中是很有用的——MVC、 Web网页和 Web Form。模型绑定到 Web Form中了,以及强类型的数据控件和一些使代码和结果相当令人信服的其他功能。我敢说,优雅。 优雅的 Web Form?疯了 !谁是这个傻瓜?

这里是一个可排序的网格,能在Web Form 4.5中创建、 编辑、 删除。作为一项试验,亲爱的读者,请做与我在这里在 ASP.NET MVC Web 页面中同样的事情。

请注意这是Damian的笔记本电脑,它是一项实验。

第一,注意是清洁的 Url。使用路由,Web Form。你没有理由不使用。

Clean URLs in WebForms. Scandalous.

这里是它的外观:

Databinding in ASP.NET Web Forms 4.5 Sneak Peek

现在在这个实验中,有个路由表。我个人想使用CRUD 公约。

    1: Routes.MapPageRoute("CategoriesNew", "Categories/New", "~/Categories_New.aspx");
    2: Routes.MapPageRoute("CategoriesEdit", "Categories/{id}", "~/Categories_Edit.aspx");
    3: Routes.MapPageRoute("CategoriesDelete", "Categories/{id}/Delete", "~/Categories_Delete.aspx");
    4: Routes.MapPageRoute("Categories", "Categories", "~/Categories.aspx");

这里是网格。现在,在你声明之前,看一看,并注意到这里虽然行不多,却有很多的功能。ItemType (是在开发者预览中的 ModelType) 强烈键入此网格到类别模型中。请注意 SelectMethod。这里你只需要提供一种方法来返回 一个iQueryable,在此例中即为GetCategories。

更新说明: 请参阅下面的评论。Damian Edwards说:"那就是说,你不需要返回 IQueryable 。你可以愉快地返回一个字符串序列并只采用额外的参数, GridView 将确保你只能检索当前请求页面中的数据并按照所选择的列排序。 "

    1: <asp:GridView runat="server" ID="categoriesGrid" CellSpacing="-1" GridLines="None"
    2:     ItemType="VS11Experiment.Model.Category" DataKeyNames="CategoryId"
    3:     AutoGenerateColumns="false"
    4:     AllowPaging="true" AllowSorting="true" PageSize="5"
    5:     SelectMethod="GetCategories">
    6:     <Columns> 
    7:        <asp:DynamicField DataField="Name" />
    8:        <asp:DynamicField DataField="Description" /> 
    9:        <asp:TemplateField>
   10:             <ItemTemplate> 
   11:                <a runat="server" href='<%# GetRouteUrl("CategoriesEdit", new { id = Item.CategoryId }) %>'>edit</a>
   12:                <a runat="server" href='<%# GetRouteUrl("CategoriesDelete", new { id = Item.CategoryId }) %>'>delete</a>
   13:             </ItemTemplate>
   14:         </asp:TemplateField>
   15:     </Columns>
   16:     <EmptyDataTemplate>
   17:         No categories found.
   18:     </EmptyDataTemplate>
   19:     <SortedAscendingHeaderStyle CssClass="asc" />
   20:     <SortedDescendingHeaderStyle CssClass="desc" />
   21:     <PagerStyle CssClass="pager" />
   22: </asp:GridView>

"好的,Hanselman,现在你打算给我们看看什么地狱般的代码隐藏呢?撒旦的卵一直照耀着我们,最后一刻却将这些讨厌的东西迸发出来?我知道你,狡猾的 Microsoft 类型,总是悄悄地藏在Lego和 Windows Phones周围"。

好的,你抓住了我。

    1: public partial class Categories : System.Web.UI.Page
    2: {
    3:     private readonly DemoWhateverDataContext _db = new DemoWhateverDataContext();
    4:  
    5:      public void Page_Load()
    6:     {
    7:         if (!IsPostBack)
    8:         {
    9:             // Set default sort expression
   10:             categoriesGrid.Sort("Name", SortDirection.Ascending);
   11:         }
   12:     }
   13:      public IQueryable<Category> GetCategories()
   14:     {
   15:         return _db.Categories;
   16:     }
   17: }

啊!我的眼睛 !等一下,不是太差。如果我可以假设在GridView上 放置默认排序,失去整个页面加载,这样将会更好。

无论你喜欢什么数据库或存储库或Web (HTTP) 服务,只要你的数据访问层返回一些 IQueryables 就行。排序是通过 LINQ来进行的,所以你的数据访问层可以做此工作,不是 ASP.NET。

所以网格中的列表类别是像样的,编辑一下看上去是什么样的呢?

Editing with ASP.NET Web Forms 4.5

如果将模型绑定添加到 ASP.NET WebForms 中,你将花更少的时间来深入到请求对象中。请注意我们在这儿不需要做到所有的那些。

请参阅在GetCategory 中, RouteData 属性如何将 id从 URL 类别/1 中拉出?

    1: public partial class Categories_Edit : System.Web.UI.Page
    2: {
    3:     private readonly DemoWhateverDataContext _db = new DemoWhateverDataContext();
    4:  
    5:      public Category GetCategory([RouteData]int? id)
    6:     { 
    7:        return _db.Categories.Find(id);
    8:     }
    9:     
   10:     public int UpdateCategory(int categoryId /* Comes from the data control itself via DataKeyNames property */)
   11:     {
   12:         var category = _db.Categories.Find(categoryId);
   13:         TryUpdateModel(category);
   14:         if (ModelState.IsValid)
   15:         {
   16:             return _db.SaveChanges();
   17:         }
   18:         return 0;
   19:     }
   20:  
   21:      protected void categoriesForm_ItemUpdated(object sender, FormViewUpdatedEventArgs e)
   22:     {
   23:         Response.RedirectToRoute("Categories");
   24:     }
   25:  
   26:      protected void categoriesForm_ItemCommand(object sender, FormViewCommandEventArgs e)
   27:     {
   28:         if (e.IsCancel())
   29:         {
   30:             Response.RedirectToRoute("Categories");
   31:         }
   32:     }
   33: }

通常人们使用ASP.NET MVC 来作为一种强力量使用PRG (获取开机自检重定向)。经常WebForms中的PostBack 被瞧不起。在上面的模式中,我们也完全可以在 Web Form中使用 PRG互动模式。请参阅如何更新项目以及重定向到一个路由。

UpdateCategory() 上的categoryId来自Form View ,它是HTTP所返回的数据。这里是片段:

    1: <asp:FormView runat="server" ID="categoriesForm" RenderOuterTable="false"
    2:             ItemType="VS11Experiment.Model.Category" DataKeyNames="CategoryId"
    3:             DefaultMode="Edit"
    4:             SelectMethod="GetCategory" UpdateMethod="UpdateCategory"
    5:             OnItemUpdated="categoriesForm_ItemUpdated"
    6:             OnItemCommand="categoriesForm_ItemCommand">

另外,你知道如何在 ASP.NET MVC 中获取由模型类本身所驱动的 不引人注目的JavaScript 验证吗?

Edit Category in ASP.NET Web Forms

在 ASP.NET MVC中 ,通常会使用 EditorFor,在 Web Form中我们有动态的控件。想法是日期获取日历,你可以使用字段模板来完全替换用户界面。该功能其实起于 Web Form动态数据,然后被移动到了 ASP.NET MVC中。当它是所有的 ASP.NET基层时,这两种方法都能让功能移动。看看我在那里做了些什么?

    1: <EditItemTemplate>
    2:     <ol>
    3:         <li><label>Name:</label>
    4:             <asp:DynamicControl runat="server" ID="name" DataField="Name" Mode="Edit" />
    5:         </li>
    6:         <li><label>Description:</label>
    7:             <asp:DynamicControl runat="server" ID="description" DataField="Description" Mode="Edit" />
    8:         </li>
    9:     </ol>
   10:     ...

而这些Form是POSTed, 你需要验证。而不是验证控件,在此情况下,由于我们已经知道了模型,我们可以使用不引人注目的验证,类似于 ASP.NET MVC。这个想法是在人们以他们想要的方式工作时,并将最好的想法引入 ASP.NET 的核心以及使常见东西更容易使用。

    1: public class Category
    2: {
    3:     [ScaffoldColumn(false), Display(Name="Id")]
    4:     public long CategoryId { get; set; }
    5:  
    6:     [Required, StringLength(100)]
    7:     public string Name { get; set; }
    8:  
    9:     [StringLength(10000), DataType(DataType.MultilineText)]
   10:     public string Description { get; set; }
   11: }

肯定的,ASP.NET Web Form可能不是你所喜欢的,就像 ASP.NET MVC 也可能不是。但请记住它是One ASP.NET。在你的工具包中有很多工具。选择那些让你快乐的吧。

One ASP.NET Diagram

* 并且不是的,此文中的地狱不是一个贬义词. ;)

相关的链接