插件混合:ASP.NET WebForms与ASP.MVC和ASP.NET动态数据并排

I wanted to write this post because there seems to be a lot of confusion about how ASP.NET WebForms, MVC and Dynamic Data all fit together. Folks may have WebForms applications and want to start looking at ASP.NET MVC but aren't sure if they need to start from scratch or not. Folks might look at Dynamic Data but mistakenly assume it's just for scaffolding administrative sites.

我之所以想写这篇文章,是因为关于ASP.NET WebForms,MVC和动态数据如何组合在一起似乎有很多困惑。 人们可能拥有WebForms应用程序,并希望开始研究ASP.NET MVC,但是不确定他们是否需要从头开始。 人们可能会看动态数据,但错误地认为它只是用于管理站点。

When you're in Visual Studio and you hit "File | New Project" you're given a number of choices. This is a starting point, but it easy to assume that this point is a fork in the road and you can mix them up.

当您使用Visual Studio并单击“文件|新建项目”时,将获得许多选择。 这是一个起点,但是很容易假设这一点是前进的道路,您可以将它们混为一谈。

File New Project Dialog

You can (and should) feel free to have Hybrid applications. You can have single Web applications that have all of these inside them (if it makes you happy):

您可以(并且应该)随意使用混合应用程序。 您可以在单个Web应用程序中包含所有这些应用程序(如果让您感到满意):

  • ASP.NET MVC

    ASP.NET MVC
  • ASP.NET WebForms

    ASP.NET Web表单
  • ASP.NET Web Services (ASMX)

    ASP.NET Web服务(ASMX)
  • WCF Services

    WCF服务
  • ASP.NET Dynamic Data

    ASP.NET动态数据
  • ASP.NET AJAX

    ASP.NET AJAX

Here's an extreme example. I'll pick ASP.NET MVC Application to start with, but it doesn't really matter. If you're confused as to what web.config entries are required, just make one of each kind of project and compare the files with your favorite diff tool (mine is Beyond Compare).

这是一个极端的例子。 我将首先选择ASP.NET MVC应用程序,但这并不重要。 如果您对需要什么web.config条目感到困惑,只需对每种项目中的一个进行创建,然后将文件与您喜欢的diff工具进行比较(我的是Beyond Compare )。

Ok, so first I've got a Hello World ASP.NET MVC application:

好的,所以首先我有一个Hello World ASP.NET MVC应用程序:

I'll add a quick LINQ to SQL database connection to the AdventureWorksLT database so I have something to query.

我将快速的LINQ to SQL数据库连接到AdventureWorksLT数据库,以便查询。

Next, I'll throw a quick ASMX Web Service into this ASP.NET MVC application that returns some data. I create it via File | New Item and select Web Service. I make a quick LINQ expression and a smaller class SmallProduct (a LINQ projection) that is returned. I also make it ScriptService, so I could call it via AJAX if I liked.

接下来,我将快速的ASMX Web服务放入此ASP.NET MVC应用程序中,该应用程序返回一些数据。 我通过File |创建它。 新建项目,然后选择Web服务。 我做了一个快速的LINQ表达式,并返回了一个较小的类SmallProduct(一个LINQ投影)。 我也将其设为ScriptService,因此我可以通过AJAX对其进行调用。

namespace Overkill
{
public class SmallProduct
{
public string Name { set; get; }
public string Color { set; get; }
public decimal Price { set; get; }
}

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class Products : System.Web.Services.WebService
{
[WebMethod]
public List<SmallProduct> GetProductsByColor(string color)
{
AdventureWorksDataContext d = new AdventureWorksDataContext();
return (from p in d.Products
where p.Color == color
select new SmallProduct
{
Name = p.Name, Color = p.Color, Price = p.ListPrice
}).ToList<SmallProduct>();
}
}
}

What does this have to do with ASP.NET MVC? Nothing. That's the point. This is an ASP.NET 2.0 style ASMX Web Service with an ASP.NET AJAX ScriptService attribute using a .NET 3.x LINQ Query to return the data, all living in an ASP.NET MVC application.

这与ASP.NET MVC有什么关系? 没有。 这才是重点。 这是具有ASP.NET AJAX ScriptService属性的ASP.NET 2.0样式ASMX Web服务,该属性使用.NET 3.x LINQ查询来返回数据,所有这些都驻留在ASP.NET MVC应用程序中。

Why doesn't ASP.NET MVC grab the request? Two reasons. First, there's an option on RouteCollection called RouteExistingFiles. It's set to false by default which causes ASP.NET MVC to automatically skip routing when a file exists on disk.

ASP.NET MVC为什么不捕获请求? 有两个原因。 首先,RouteCollection上有一个名为RouteExistingFiles的选项。 默认情况下,它设置为false,这会导致ASP.NET MVC在磁盘上存在文件时自动跳过路由。

if (!this.RouteExistingFiles)
{
string appRelativeCurrentExecutionFilePath = httpContext.Request.AppRelativeCurrentExecutionFilePath;
if (((appRelativeCurrentExecutionFilePath != "~/") && (this._vpp != null)) && (this._vpp.FileExists(appRelativeCurrentExecutionFilePath) || this._vpp.DirectoryExists(appRelativeCurrentExecutionFilePath)))
{
return null;
}
}

Because the default Route in Global.asax isn't greedy enough to care even if we were routing all requests:

因为Global.asax中的默认Route不够贪婪 即使在路由所有请求时也要注意:

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);

}

However, in my personal experience, File.Exists is a very expensive operation (very is relative…it's expensive because it hits the disk at all). A best (and example of attention to detail) practice would be to put in an IgnoreRoute call for those pages, directories, and/or HttpHanders. For example:

但是,以我个人的经验,File.Exists是一个非常昂贵的操作(非常相对……这很昂贵,因为它完全会碰到磁盘)。 最好的(和关注细节的示例)做法是对这些页面,目录和/或HttpHanders进行IgnoreRoute调用。 例如:

routes.IgnoreRoute("{myWebForms}.aspx/{*pathInfo}");
routes.IgnoreRoute("{myWebServices}.asmx/{*pathInfo}");
routes.IgnoreRoute("myCustomHttpHandler.foo/{*pathInfo}");
routes.IgnoreRoute("Contents/{*pathInfo}");

Here I'm ignoring .aspx, .asmx, a custom HttpHandler with a custom extension and the whole of the Contents folder. I might even want to set routes.RouteExistingFiles = true which would turn off the File.Exists check and put ALL the pressure for routing on my routes. I'll need to be more careful and explicit, but that's rarely a bad thing. You could also just structure your site such that all your non-MVC things live in their own folder. It's up to you.

在这里,我忽略了.aspx,.asmx,具有自定义扩展名和整个Contents文件夹的自定义HttpHandler。 我什至可能要设置route.RouteExistingFiles = true,这将关闭File.Exists检查并将所有路由压力施加到我的路由上。 我需要更加小心和明确,但这很少是一件坏事。 您也可以只构建站点,使所有非MVC内容都位于它们自己的文件夹中。 由你决定。

Now, let me add a WebForm and *gasp* drag a GridView into it. Wow, I'm a bad person, I've just used the Designer. I was productive so, but what price my immortal soul? ;)

现在,让我添加一个WebForm并* gasp *将GridView拖入其中。 哇,我是一个坏人,我刚刚使用过Designer。 我本来就是有生产力的,但是我不朽的灵魂要付出什么代价呢? ;)

WebForm with a GridView

Seriously, though, use what makes you happy. This grid is kind of lame, so I'll add some ASP.NET DynamicData. However, while you usually see Dynamic Data from a File | New Application point of view, I'm going to just bring a DynamicDataManager control onto the page. You'll also want to confirm that you have DynamicData controls listed in your web.config:

但是,认真地使用使自己快乐的东西。 该网格有点la脚,因此我将添加一些ASP.NET DynamicData。 但是,尽管通常会从文件|列表中看到动态数据。 从新应用程序的角度来看,我将把DynamicDataManager控件带到页面上。 您还需要确认在web.config中列出了DynamicData控件:

<pages>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add tagPrefix="asp" namespace="System.Web.DynamicData" assembly="System.Web.DynamicData, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</controls>
</pages>

I'll add a few things to my WebForms page:

我将在WebForms页面中添加一些内容:

<div>
<asp:DynamicDataManager ID="DynamicDataManager1" runat="server" />
<asp:GridView ID="GridView1" runat="server" DataSourceID="GridDataSource"
AutoGenerateColumns="false" DataKeyNames="ProductID" AllowPaging="true" AllowSorting="true">
<Columns>
<asp:DynamicField DataField="Name" />
<asp:DynamicField DataField="ProductNumber" />
<asp:DynamicField DataField="Color" />
<asp:DynamicField DataField="ListPrice" />
</Columns>
</asp:GridView>
<asp:LinqDataSource ID="GridDataSource" runat="server" EnableDelete="true"
ContextTypeName="Overkill.AdventureWorksDataContext" TableName="Products"/>
</div>

In the Global.asax.cs, I'll add these two lines to let the DynamicData system know that we're working on this DataContext:

在Global.asax.cs中,我将添加以下两行以使DynamicData系统知道我们正在处理此DataContext:

MetaModel model = new MetaModel();
model.RegisterContext(typeof(AdventureWorksDataContext), new ContextConfiguration() { ScaffoldAllTables = false });

Then, the most important part, I'll want to bring in the ~\DynamicData folder, since that's where DynamicData finds all of its templates. For this example, I really only need ~\DynamicData\FieldTemplates as I'm only using the smallest bit of Dynamic Data functionality.

然后,最重要的部分,我要引入〜\ DynamicData文件夹,因为DynamicData可以在其中找到所有模板。 对于此示例,我实际上只需要〜\ DynamicData \ FieldTemplates,因为我仅使用了最小的动态数据功能。

To do this easily and quickly, I usually make a throwaway new DynamicData Web Application in another instance of Visual Studio, making sure to give it the same name (and hence, namespace) as the one I'm working on. Then I just drag that project's DynamicData folder over into my original application, and ensure that all the designer files and code-behinds are included in the project (Show All files, then right click each one, Include in Project). The rumor is that there will be a quick way in the future to bring a fresh DynamicData folder into an existing app.

为了轻松,快速地完成此任务,我通常在Visual Studio的另一个实例中创建一个废弃的新DynamicData Web应用程序,确保为其赋予与我正在使用的名称相同的名称(并因此为其命名空间)。 然后,我只需将该项目的DynamicData文件夹拖到我的原始应用程序中,并确保所有设计器文件和代码隐藏都包含在项目中(“显示所有文件”,然后右键单击每个文件,包括在“项目”中)。 有传言说,将来会有一种快速的方法将一个新的DynamicData文件夹带到现有的应用程序中。

Now, I'll hit my page again and then I get shiny Dynamic Data goodness.

现在,我将再次点击页面,然后我将获得动态数据优势。

DynamicData

At this point I've got a WebForm, Dynamic Data, and a totally random unused WebService living inside an ASP.NET MVC application. Of course, now this begs the question "Is this an ASP.NET MVC application."

至此,我已经有了一个WebForm,动态数据以及一个完全随机的未使用的WebService,它们都驻留在ASP.NET MVC应用程序中。 当然,现在这引出了一个问题:“这是ASP.NET MVC应用程序吗?”。

Oh, you wanted MVC used also? ;) I'll add a quick Products method to the HomeController:

哦,您还想使用MVC吗? ;)我将一个快速的Products方法添加到HomeController中:

public ActionResult Products(string color)
{
AdventureWorksDataContext d = new AdventureWorksDataContext();
var smallProducts = (from p in d.Products
where p.Color == color
select new SmallProduct
{
Name = p.Name,
Color = p.Color,
Price = p.ListPrice
}).ToList<SmallProduct>();
return View("Products", smallProducts);
}

Then a quick view, making sure it's derived from ViewPage<List<SmallProduct>>:

然后快速查看,确保它是从ViewPage <List <SmallProduct >>派生的:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Products.aspx.cs" Inherits="Overkill.Views.Home.Products" %>
<%@ Import Namespace="Overkill" %>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
<h2><%= Html.Encode(ViewData["Message"]) %></h2>
<p>
<ul>
<% foreach (SmallProduct p in ViewData.Model)
{ %>
<li><%=p.Name %> <%=p.Price.ToString("C")%></li>

<% } %>
</ul>
</p>
</asp:Content>

And that works also, visiting /Home/Products, ensuring there's a route that matches. I'll make this Route overly specific:

而且,访问/ Home / Products并确保存在匹配的路由也可以。 我将使此路线过于具体:

routes.MapRoute(
"ProductsWithColor",
"Home/Products/{color}",
new { controller = "Home", action = "Products", color = "Red" }
);

And it renders like this:

它呈现如下:

MVCList

I hope this helps and it's more clear now that it's just "an ASP.NET application."

我希望这会有所帮助,现在更清楚的是,它只是“一个ASP.NET应用程序”。

You can feel free to mix and match. Not everyone can (or should) rewrite an existing ASP.NET application, so it is nice that everyone can use some new features in the same ASP.NET application as their existing functionality.

您可以随意混搭。 并非每个人都可以(或应该)重写现有的ASP.NET应用程序,因此,每个人都可以在同一个ASP.NET应用程序中使用一些新功能作为其现有功能,这是很好的。

翻译自: https://www.hanselman.com/blog/plugin-hybrids-aspnet-webforms-and-aspmvc-and-aspnet-dynamic-data-side-by-side

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值