经常看见有人问VS项目里新建网站和新建Web应用程序有什么区别,而回答也都很多很多。
我就再次引用下MSDN的回答吧!
MSDN 官方的回答页面地址:http://msdn.microsoft.com/zh-cn/library/k33801s3(v=vs.100).aspx
原文如下:
Web 应用程序项目与网站项目
.NET Framework 4
Web application projects or Web site projects.‘>在
Visual Studio 中,可以创建“Web 应用程序项目”或“网站项目”。 每种项目类型各有优缺点,要选择可以满足需要的最佳项目类型,应了解各项目类型之间的差异。
创建项目之前,必须选择合适的项目类型,原因是从一种项目类型转换到另一种项目类型并不可行。
注意 |
---|
在某些情况下无法进行选择。 |
本主题包含以下各节:
- 方案
- 差异摘要
- 项目文件结构
- 编译
- 部署
方案
优先选择
Web 应用程序项目的情况包括:
- 需要在不停止调试会话的情况下能够编辑代码。
- 需要对与
ASP.NET 页关联的类文件中的代码运行单元测试。 - 需要从独立类中引用与页和用户控件关联的类。
- 您希望在多个
Web 项目之间建立项目相关性。 - 您希望编译器为整个站点创建单个程序集。
- 您要控制为站点生成的程序集的名称和版本号。
- 需要使用
MSBuild 或 Team Build 编译项目。 例如,您可能希望添加预先生成和后期生成步骤。 - 需要避免将源代码放置在生产服务器上。
- 需要使用
Visual Studio 2010 中提供的自动化部署工具。
优先选择网站项目的情况包括:
- 需要在单个
Web 项目中同时包含 C# 和 Visual Basic 代码。 (默认情况下,是根据项目文件中的语言设置编译
Web 应用程序的。 可以设置例外情况,但相对较难。) - 需要在
Visual Studio 中打开生产站点和使用 FTP 对其进行实时更新。 - 不希望必须显式编译项目才能部署项目。
- 如果预编译站点,您希望编译器为站点创建多个程序集,可以是每个页面或用户控件一个程序集,也可以是每个文件夹一个或多个程序集。
- 您希望能够通过仅将新版本复制到生产服务器,或通过在生产服务器上直接编辑文件来更新生产中的各个文件。
- 如果预编译站点,您希望能更新各
ASP.NET 网页(.aspx 文件),而无需重新编译整个网站。 - 您希望在生产服务器上保留源代码,以便用作附加备份副本。
差异摘要
下表总结了主要差异。
区域 |
Web 应用程序项目 |
网站项目 |
---|---|---|
项目文件结构 |
Visual |
不存在项目文件(.csproj |
编译 |
|
|
命名空间 |
默认情况下,将显式命名空间添加到页面、控件和类中。 |
默认情况下,不将显式命名空间添加到页面、控件和类中,但您可以手动添加它们。 |
部署 |
|
|
项目文件结构
Web
应用程序项目使用 Visual Studio 项目文件(.csproj 或 .vbproj)来跟踪有关项目的信息。 除其他任务以外,这还使得指定项目中要包含或排除哪些文件,以及因此在生成期间编译哪些文件成为可能。
对于网站项目,文件夹结构中的所有文件会被自动视为包含在网站中。
如果您希望从编译中排除某些文件,必须从网站项目文件夹中移除文件或将其文件扩展名更改为不由
IIS 编译和提供的扩展名。
使用
Web 应用程序项目中的项目文件具有以下优点:
- 易于暂时从站点移除文件,但仍确保不会失去对它们的跟踪,因为这些文件保留在文件夹结构中。
例如,如果页面没有为部署准备就绪,您可以暂时从生成中排除它,而无需从文件夹结构中将其删除。
您可以部署编译的程序集,然后再次将文件包括在项目中。
这在使用源代码管理储存库时尤为重要。
在网站项目中使用无项目文件的文件夹结构具有以下优点:
- 您不必专门在
Visual Studio 中管理项目的结构。 例如,您可以通过使用
Windows 资源管理器将文件复制到项目中或从项目中删除文件。
编译
对于
Web 应用程序项目,通常在 Visual Studio 中生成项目,或通过使用不是生产 IIS 服务器的计算机上的 ASP.NET
批处理编译器生成项目。 项目中的所有代码隐藏类文件和独立类文件都编译为一个程序集,然后将其放在
Web 应用程序项目的 Bin 文件夹中。 (.aspx
和 .ascx 文件以与网站项目类似的方式进行动态编译。)
对于网站项目,您不必手动编译项目。
网站项目通常由
ASP.NET(在开发计算机和生产 IIS 服务器上)进行动态编译。 您可以在批处理编译模式(通常为每个文件夹生成一个程序集)和固定编译模式(通常为每个页面或用户控件生成一个程序集)之间选择。
Web
应用程序项目的编译模型具有以下优点:
- 您可以使用
MSBuild 来创建自定义批处理编译过程。 - 指定程序集特性(如名称和版本)非常简单。
- 事先编译可确保在生产服务器上编译站点期间用户无须等待。
(如果站点非常大,网站项目的动态编译可能需要花费大量时间。
动态编译在更新站点之后收到站点资源请求时发生,并且当编译所需资源时,触发编译的请求可能会被延迟。
如果延迟不可接受,则可以预编译站点。
但因此会失去动态编译的某些优点。) - 您可以完全控制项目文件夹结构中放置代码文件的位置,以及项目中的类互相引用的方式。
(动态编译要求在整个站点中使用的所有类的源代码必须位于
App_Code 文件夹中。 您不能从
App_Code 中的类引用页面或用户控件类。)
网站项目的编译模型具有以下优点:
- 您可以测试特定的页面,而不管其他页面的状态。
这是因为运行单个页面不需要成功编译整个站点,仅需编译该页面和该页面所依赖的任何组件,如
App_Code 文件夹或 Global.asax 文件中的代码。 (在
Web 应用程序项目中,如果站点中任何位置存在编译错误,则不能创建程序集,因此不能进行测试,甚至连测试所编译站点的部分内容也不行。) - 在生产中更新网站非常容易。
可以更新生产服务器上的各个源代码文件,而无需以显式方式重新编译站点。
即使由于编译错误其他文件未准备就绪,也可以更新各个为部署准备就绪的文件。
还可以直接在
Visual Studio 中打开生产 IIS 服务器上的网站,并实时更新该网站。 - 在某些情况下,预编译为多个程序集具有性能优势。
一个典型示例是具有许多页面,并为这些页面编写了大量代码的站点。
其中大多数页面极少被请求,只有某些页面经常受到使用。
如果将这样的站点编译成多个程序集,生产服务器就可以仅加载当前请求所需的程序集。
如果未请求某个页面,则不会加载其对应的程序集。
注意 |
---|
网站项目和 |
部署
若要部署
Web 应用程序项目,需将通过编译该项目创建的程序集复制到 IIS 服务器。 相反,若要部署网站项目,通常是将项目源文件复制到
IIS 服务器。
Web
应用程序项目部署策略的优点包括:
- 可以避免将源代码部署到
IIS 服务器。 在某些情况下,例如在共享承载环境中,您可能会关注对
IIS 服务器上源代码进行的未经授权的访问。 (对于网站项目,可能通过在开发计算机上进行预编译并部署所生成的程序集而不是源代码来避免此风险。
不过,在这种情况下,会失去轻松更新站点的某些好处。) - 除将程序集或代码复制到服务器之外,部署通常还涉及其他任务。
例如,数据库脚本可能必须在生产中运行,Web.config
文件中的连接字符串可能需要针对生产服务器进行更改。 Visual
Studio 提供了一些处理 Web 应用程序项目以自动执行其中许多任务的工具,如一键式发布。 这些工具对于网站项目不可用。
网站项目部署策略的优点包括:
- 如果对
Web 应用程序进行少量更改,则不必重新部署整个应用程序。 而是可以只将更改过的文件复制到生产
IIS 服务器。 另外,还可在生产服务器上直接编辑文件。
(因为
Web 应用程序项目的代码文件将被编译成单个程序集文件,所以即使进行少量更改,也必须部署整个站点,除非更改只是针对 .aspx 或 .ascx
文件。)
// =scripts.length){delete mtps.injectScripts;return}script=scripts[index];elem=document.createElement("script");elem.className="mtps-injected";elem.async=!1;var isLoaded=!1,timeoutId=0,injectNextFnName="",injectNext=elem.onerror=function(){isLoaded||(isLoaded=!0,inject(scripts,index+1),window.clearTimeout(timeoutId),elem.onload=elem.onerror=elem.onreadystatechange=null,injectNextFnName&&delete mtps[injectNextFnName],elem.removeEventListener&&elem.removeEventListener("load",injectNext,!1))};elem.addEventListener?elem.addEventListener("load",injectNext,!1):elem.readyState==="uninitialized"?elem.onreadystatechange=function(){(this.readyState==="loaded"||this.readyState==="complete")&&injectNext()}:elem.onload=injectNext;script.hasOwnProperty("url")?(timeoutId=window.setTimeout(injectNext,12e4),elem.src=script.url):(injectNextFnName="_injectNextScript_"+index,mtps[injectNextFnName]=injectNext,timeoutId=window.setTimeout(injectNext,2e3),elem.text="try {\n"+script.txt+"\n} finally { MTPS."+injectNextFnName+" && MTPS."+injectNextFnName+"(); }");parent.appendChild(elem)}var mtps=window.MTPS||(window.MTPS={}),parent=document.getElementsByTagName("head")[0];mtps.injectScripts=function(scripts){inject(preload(scripts),0)}})(window,document);
MTPS.injectScripts([
{ txt: "/**/\r\n(window.MTPS || (window.MTPS = {})).cdnDomains || (window.MTPS.cdnDomains = { \r\n\t\"image\": \"http://i.msdn.microsoft.com\", \r\n\t\"js\": \"http://i2.msdn.microsoft.com\", \r\n\t\"css\": \"http://i3.msdn.microsoft.com\", \r\n\t\"xap\": \"http://msdn.microsoft.com\"\r\n});\r\n/**/" },
{ url: "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.2.min.js" },
{ txt: "//\n var literalNormalizedUrl = \u0027/zh-cn/library/dd547590(d=printer,l=zh-cn,v=vs.100).aspx\u0027;\n var wt_nvr_ru = \u0027WT_NVR_RU\u0027;\n var wt_fpcdom = \u0027.microsoft.com\u0027;\n var wt_domlist = \u0027msdn.microsoft.com\u0027;\n var wt_pathlist = \u0027\u0027;\n var wt_paramlist = \u0027DCSext.mtps_devcenter\u0027;\n var wt_siteid = \u0027MSDN\u0027;\n var gDomain = \u0027m.webtrends.com\u0027;\n var gDcsId = \u0027dcsmgru7m99k7mqmgrhudo0k8_8c6m\u0027;\n var gFpc = \u0027WT_FPC\u0027;\n\n\n\n if (document.cookie.indexOf(gFpc + \"=\") == -1) {\n var wtidJs = document.createElement(\"script\");\n wtidJs.src = \"//\" + gDomain + \"/\" + gDcsId + \"/wtid.js\";\n document.getElementsByTagName(\"head\")[0].appendChild(wtidJs);\n }\n\n\n\n var detectedLocale = \u0027zh-cn\u0027;\n var wtsp = \u0027msdnlib_webdev\u0027;\n var gTrackEvents = \u00270\u0027;\n/**/" },
{ txt: "/**/\n var omni_guid = \"6606a27e-a79a-42e3-9e1c-52de323535c5\";\n/**/" },
{ txt: "//\n\n window.appInsightsId = \u002760854590-027a-4ae4-98be-2741a40f355f\u0027;\n //" },
{ url: "http://i2.msdn.microsoft.com/Combined.js?resources=0:Utilities,1:Layout,2:Header,2:Footer,3:Feedback,0:Topic,4:webtrendsscript,5:omni_rsid_MSDN,0:AppInsightsPerf,6:SearchBox;/Areas/Epx/Content/Scripts:0,/Areas/Centers/Themes/Base/Content:1,/Areas/Centers/Themes/StandardDevCenter/Content:2,/Areas/Epx/Shared/Content:3,/Areas/Global/Content/Webtrends/resources:4,/Areas/Global/Content/Omniture/resources/MSDN:5,/Areas/Epx/Themes/Base/Content:6\u0026amp;hashKey=5ED483CE4D1C4F29BB3535DBA07833E0" },
{ url: "http://i1.services.social.microsoft.com/search/Widgets/SearchBox.jss?boxid=HeaderSearchTextBox\u0026btnid=HeaderSearchButton\u0026brand=Msdn\u0026loc=zh-cn\u0026focusOnInit=false\u0026emptyWatermark=true\u0026searchButtonTooltip=搜索 MSDN" },
{ url: "http://i2.msdn.microsoft.com/Combined.js?resources=0:PrintExportButton,1:Toc,1:NavigationResize;/Areas/Library/Themes/Base/Content:0,/Areas/Library/Content:1\u0026amp;hashKey=5697C9CD323F5AF47E3C6402F1CAF960" },
{ txt: "//\n MTPS = window.MTPS || {};\n MTPS.Translation = window.MTPS.Translation || {};\n\n MTPS.Translation.TranslationType = 0;\n \n \n //" },
{ url: "http://i2.msdn.microsoft.com/Combined.js?resources=0:jquery.popup,0:Translator,1:FeedbackCounter;/Areas/Library/Content:0,/Areas/Epx/Shared/Content:1\u0026amp;hashKey=1FDD911346A8AAC65E131ED3A9F62283" },
{ txt: "MTPS = window.MTPS || {}; MTPS.LocalizedStrings = window.MTPS.LocalizedStrings || {}; MTPS.LocalizedStrings.ExpandButtonTooltip = \u0027展开\u0027; MTPS.LocalizedStrings.CollapseButtonTooltip = \u0027折叠\u0027; MTPS.LocalizedStrings.EnhancedExpandTooltip = \u0027单击以展开。双击以全部展开。\u0027; MTPS.LocalizedStrings.EnhancedCollapseTooltip = \u0027单击以折叠。双击以全部折叠。\u0027; MTPS.LocalizedStrings.ExpandAllButtonTooltip = \u0027全部展开\u0027; MTPS.LocalizedStrings.CollapseAllButtonTooltip = \u0027全部折叠\u0027;" },
{ url: "http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js" },
{ url: "http://i2.msdn.microsoft.com/Combined.js?resources=0:CommunityContent,0:LibraryMemberFilter,1:Toc_Fixed,1:CodeSnippet,1:TopicNotInScope,1:CollapsibleArea,1:VersionSelector,1:SurveyBroker;/Areas/Library/Content:0,/Areas/Epx/Content/Scripts:1\u0026amp;hashKey=7DFFEC88BE1B5AB6142D05C857F9E403" },
{ txt: "$(document).ready(function() {\n try {\n var token = $(\"#globalRequestVerification input[name=\u0027__RequestVerificationToken\u0027]\").clone();\n $(\"#siteFeedbackForm\").append(token);\n } catch(err) {\n \n }\n });" }
]);
// ]]>