ASP.NET的隐藏功能


292

存在该问题是因为它具有历史意义,但是对于本站点而言,它不是一个很好的主题问题,因此,请勿将其用作您可以在此处提出类似问题的证据。

更多信息:https//stackoverflow.com/faq


在边缘场景中总会有一些有用的功能,但是由于这个原因,大多数人都不了解它们。我要的是教科书通常不教授的功能。

你知道些什么?


好问题,希望可以多次投票!
加文·米勒

1
同意 我喜欢这样的线程。框架的深度如此之大,以至于您有时会对从未存在的事物感到惊讶。
Deane

我正在从该主题的响应中学到很多很棒的新技巧-谢谢!:)
Maxim Zaslavsky

16
不应将这些名称称为“ ..的隐藏功能”,而不是“ ..的隐藏功能”,因为大多数答案在MSDN或其他地方都有详细记录,只是不为人们所熟知或使用。
约翰·K

meta.stackexchange.com/questions/56669/...meta.stackexchange.com/questions/57226/...和相关元职位,讨论是否恰当和关闭。

Answers:


335

在测试期间,您可以将电子邮件发送到计算机上的文件夹而不是SMTP服务器。将其放在您的web.config中:

<system.net>
    <mailSettings>
        <smtp deliveryMethod="SpecifiedPickupDirectory">
            <specifiedPickupDirectory pickupDirectoryLocation="c:\Temp\" />
        </smtp>
    </mailSettings>
</system.net>

6
真?我正要安装假的SMTP服务器,例如Dumbster。我隐藏了宝石。
Eduardo Molteni

2
有谁知道您是否可以为目录位置指定UNC共享?
Mark Sherretta 09年

32
更好的是,将其放在开发箱中的machine.config中,这样就不必在创建的每个应用程序上都更改web.config。
Max Toro

您可以将其设置为仅在本地主机上吗?这样,您不必每次都更改它吗?
chobo2

没有设置。您必须使用其他方法(Web部署项目,构建任务等)来管理配置差异
John Sheehan 2009年

210

如果 在Web应用程序目录的根目录中放置一个名为app_offline.htm的文件,则ASP.NET 2.0+将关闭该应用程序并停止正常处理该应用程序的任何新传入请求,仅显示app_offline.htm的内容。提交所有新请求

在重新部署(或回滚)对生产服务器的更改时,这是显示“站点暂时不可用”通知的最快,最简单的方法。

另外,正如marxidad指出的那样,请确保文件中至少有512字节的内容,以便IE6可以正确呈现它。


10
别忘了IE的“友好”消息的解决方法:tinyurl.com/app-offline-friendly
Mark Cidade

1
哎哟! 将其与MOSS 2007一起使用时要小心。它仅适用于自上次IIS重新启动以来已访问的页面。所以,如果你收藏此页到您的WSS虚拟根目录,然后尝试打开一个以前没有访问的页面,你会得到一个404
马克·

1
@Marc-从Scott Guthrie那里得到了这个提示,如果您感到慷慨,那么如果您对Gu的文章发表评论,将会帮助很多SharePoint开发人员避免这种情况:weblogs.asp.net/scottgu/archive/2005/10/ 06 / 426755.aspx
Troy DeMonbreun

另外,在所有请求完成后,这还将触发App Domain的回收并关闭所有打开的数据库连接。
Bart Verkoeijen 2011年

需要注意的是:IIS返回HTTP状态代码为404的app_offline.htm内容。如果搜索引擎在离线模式下徘徊并尝试为您的网站编制索引,则可能不会满意结果。但这对我的私人公司Web应用程序非常有用!
拉里·西尔弗曼

119
throw new HttpException(404, "Article not found");

这将被ASP.NET捕获,它将返回customErrors页面。在最近的.NET每日贴士中了解到这一点


一些开发人员可能会争辩说,最好将它们手动包装在HttpContext.Response中,而不是抛出一个异常,这在.NET书籍中是非常昂贵的操作。
lubos hasko

这不是不好的形式吗?您正在显示404错误,而您想显示一个错误/异常。
Donnie Thomas

1
我能想到的一种情况是,如果有人恶意弄乱了参数并将无效内容放入其中,则您可能希望使用通用404而不是特定错误。
约翰·希恩

3
纯粹是因为我现在知道.NET Tip of the Day网站才被推荐。

仅当您将其扔到httpModule或httpHandler中时,它才有效
Khaled Musaied 2009年

75

这是最好的。将此添加到您的web.config中,以加快编译速度。这是通过此QFE发布的3.5SP1 。

<compilation optimizeCompilations="true">

快速总结:我们在ASP.NET中引入了一个新的optimizeCompilations开关,在某些情况下可以大大提高编译速度。有一些问题,因此请继续阅读以获取更多详细信息。该开关当前可作为3.5SP1的QFE使用,并将成为VS 2010的一部分。

ASP.NET编译系统采用非常保守的方法,这使得它在“顶级”文件发生更改时会抹去以前所做的任何工作。“顶级”文件包括bin和App_Code中的所有内容,以及global.asax。虽然这对于小型应用程序很好用,但对于大型应用程序几乎变得不可用。例如,某个客户遇到一种情况,即在对“ bin”程序集进行任何更改后,刷新页面需要10分钟。

为了减轻痛苦,我们添加了“优化”编译模式,该模式采用了保守得多的方法进行重新编译。

通过这里


6
是VS 2010的“默认设置”还是我仍然应该尝试一下?
M4N

73
  • HttpContext.Current将始终使您能够访问当前上下文的Request / Response / etc。,即使您无权访问Page的属性(例如,从松散耦合的帮助器类)。

  • 您可以通过调用Response.Redirect(url false 将用户重定向到另一个页面,然后继续在同一页面上执行代码。

  • 如果只需要一个已编译的Page(或任何IHttpHandler),则不需要.ASPX文件。只需将路径和HTTP方法设置为指向web.config文件中元素中的类即可。<httpHandlers>

  • 对象可以从被检索.ASPX文件编程通过调用PageParser.GetCompiledPageInstance(virtualPath,aspxFileName,上下文)


关于Response.Redirect(url,false)-那是我很长一段时间以来一直希望的..我不知道我如何错过它,但是比xxx
Subliminal Hash

1
有人可以解释您将如何处理吗?我知道它具有某些价值,但我不知道为什么...
Deane

5
如果您想将用户重定向到其他地址,但仍然需要执行一些后端处理(例如,在继续在后台生成报告的同时,重定向到报告的生成状态页的报告生成请求)
Mark Cidade

有人可以解释一下PageParser.GetCompiledPageInstance(..)的有用情况吗?文档说这是为基础设施使用的-它返回一个IHttpHandler类型,所以我不知道如何实际使用它。
约翰·K

@jdk:过去我在为* .aspx请求覆盖默认处理程序时使用过它,因此我可以使用动态内存中的IHttpHandler对象,也可以将GetCompiledPageInstance()用于物理* .aspx文件。
马克·西达德

70

machine.config级别的零售模式:

<configuration>
  <system.web>
    <deployment retail="true"/>
  </system.web>
</configuration>

覆盖web.config设置以将debug强制设置为false,打开自定义错误并禁用跟踪。无需再忘记在发布之前更改属性-只需将它们全部配置为用于开发或测试环境并更新生产零售设置即可。


1
我有时忘记发布之前将编译调试更改为false,这会对性能产生负面影响。没问题了!
罗伊·廷克

59

在内容页面中为MasterPages启用智能感知
我确信这是一个鲜为人知的黑客

大多数时候,您必须使用findcontrol方法并在要使用内容页面时将控件从内容页面投射到母版页面中, 一旦您执行此操作,MasterType指令将在visual studio中启用智能感知

只需向页面添加一个指令

<%@ MasterType VirtualPath="~/Masters/MyMainMasterPage.master" %>

如果您不想使用虚拟路径,而是使用类名,则

<%@ MasterType TypeName="MyMainMasterPage" %>

此处获取全文


有时候,使用FindControl有时会很忙,谢谢您的提示!
亚历山大·布瑞斯布瓦

4
使用此功能可能会导致意外的行为。见stackoverflow.com/questions/1998931/...
citronas

我个人认为功能应该不为人们所熟悉,它将页面与母版页面相结合。如果最终使用了母版页的属性/方法,然后更改了母版页,那么最终将导致维护噩梦。
菲尔

@Phil:有时是必需的,并且可以通过静态类型访问母版页比FindControl方法要好得多。至少您会收到编译器消息并可以快速修复它。
2011年

58

HttpContext.Items作为请求级缓存工具


2
这也是我要说的,我在嵌套控件中使用它来传递/接收请求级别信息。ii在MVC中也使用它来存储基于部分视图的要附加的js文件列表。
2009年

1
当我使用asp.net路由将从url中获取的参数传递给我的页面时,会使用此方法。(不适用于MVC)非常适合url重写,并且非常灵活。
亚历山大·布瑞斯布瓦

嗯,只是想到了我可以用它代替Session的地方-ta!
迈克·金斯科特

52

我想到两件事:

1)您可以从代码打开和关闭跟踪:

#ifdef DEBUG 
   if (Context.Request.QueryString["DoTrace"] == "true")
                {
                    Trace.IsEnabled = true;
                    Trace.Write("Application:TraceStarted");
                }
#endif

2)您可以仅使用一个共享的“代码隐藏”文件来构建多个.aspx页。

建立一个class .cs文件:

public class Class1:System.Web.UI.Page
    {
        public TextBox tbLogin;

        protected void Page_Load(object sender, EventArgs e)
        {

          if (tbLogin!=null)
            tbLogin.Text = "Hello World";
        }
    }

然后您可以拥有任意数量的.aspx页(在删除VS生成的.designer.cs和.cs代码后):

  <%@ Page Language="C#"  AutoEventWireup="true"  Inherits="Namespace.Class1" %>
     <form id="form1" runat="server">
     <div>
     <asp:TextBox  ID="tbLogin" runat="server"></asp: TextBox  >
     </div>
     </form>

您可以在ASPX中具有不出现在Class1中的控件,反之亦然,但是您需要记住检查控件是否为null。


我本来会投票赞成,但没有票。我将尝试并记得回来投票。我不知道我们可以为多个页面使用相同的“代码隐藏”文件。不确定如何运作。
Vaibhav

5
还有其他人认为允许您从URL激活跟踪存在安全风险吗?(#1)我不会拒绝这个问题,但是了解那里的风险很重要。
凯文·高夫

5
绝对,您应该将该代码真正放入#ifdef DEBUG #endif块中
Radu094 '09

很棒的评论,指出了安全方面。
Vaibhav

2
为什么从url激活跟踪存在安全风险?如何用来伤害我?
Kamarey

48

您可以使用:

 Request.Params[Control.UniqueId] 

要获取控件的值,请先初始化viewstate(此时Control.Text等将为空)。

这对于Init中的代码很有用。


Viewstate初始化不与Request.Params一起使用。在引发控件实现的IPostBackDataHandler的LoadPostData方法之前使用它。
chapluck 2010年

46

WebMethods。

您可以将ASP.NET AJAX回调用于放置在ASPX页面中的Web方法。您可以使用[WebMethod()]和[ScriptMethod()]属性来装饰静态方法。例如:

[System.Web.Services.WebMethod()] 
[System.Web.Script.Services.ScriptMethod()] 
public static List<string> GetFruitBeginingWith(string letter)
{
    List<string> products = new List<string>() 
    { 
        "Apple", "Banana", "Blackberry", "Blueberries", "Orange", "Mango", "Melon", "Peach"
    };

    return products.Where(p => p.StartsWith(letter)).ToList();
}

现在,在您的ASPX页面中,您可以执行以下操作:

<form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" />
        <input type="button" value="Get Fruit" onclick="GetFruit('B')" />
    </div>
</form>

并使用以下代码通过JavaScript调用服务器端方法:

    <script type="text/javascript">
    function GetFruit(l)
    {
        PageMethods.GetFruitBeginingWith(l, OnGetFruitComplete);
    }

    function OnGetFruitComplete(result)
    {
        alert("You got fruit: " + result);
    }
</script>

45

在开始长时间运行的任务之前,请检查客户端是否仍处于连接状态:

if (this.Response.IsClientConnected)
{
  // long-running task
}

44

ASP.NET的一项鲜为人知且很少使用的功能是:

标签映射

它很少使用,因为在特定情况下您需要它,但是当您需要它时,它非常方便。

有关此鲜为人知的功能的一些文章:

在ASP.NET中
使用标签映射在ASP.NET中进行标签映射

从上一篇文章中可以得出:

标记映射允许您在编译时在Web应用程序的每个页面上交换兼容的控件。一个有用的示例是,如果您有一个普通的ASP.NET控件(例如DropDownList),并且希望将其替换为派生自DropDownList的自定义控件。这可能是已自定义以提供更优化的查找数据缓存的控件。无需编辑每个Web表单并将内置的DropDownLists替换为自定义版本,您可以使ASP.NET实际上通过修改web.config来实现:

<pages>
 <tagMapping>
   <clear />
   <add tagType="System.Web.UI.WebControls.DropDownList"
        mappedTagType="SmartDropDown"/>
  </tagMapping>
</pages>

这对于您团队中的其他开发人员会非常困惑
AykutAkıncı

1
@Aykut-确实可以,这就是为什么我声明它的用途非常狭窄,但是,在需要时它非常方便。另外,我将确保对Tag Mapping的任何用法进行非常清晰的记录,以免造成任何混淆和歧义。
CraigTP

43

HttpModules。该架构是疯狂的优雅。也许不是隐藏的功能,但仍然很酷。


3
HttpModules是高级功能,但我不会称其为稀有或使用较少(或称我为天真)。但是,是的,我喜欢建筑。
Vaibhav

+1,因为许多经验丰富的开发人员可能对HttpModules有所了解,但并不完全了解他们与请求的关系。(与HttpHandlers相同)
John Bubriski

34

您可以在.aspx页面中使用ASP.NET注释来注释掉页面的整个部分,包括服务器控件。被注释掉的内容将永远不会发送给客户端。

<%--
    <div>
        <asp:Button runat="server" id="btnOne"/>
    </div>
--%>

5
有些人真的不知道有评论吗?
乔·菲利普斯

7
当您在<!-评论中找到半个aspx页面时,我会喜欢它
Bryan Rehbein

这是ASP.NET的
基本

34

代码表达式生成器

样本标记:

Text = '<%$ Code: GetText() %>'
Text = '<%$ Code: MyStaticClass.MyStaticProperty %>'
Text = '<%$ Code: DateTime.Now.ToShortDateString() %>'
MaxLenth = '<%$ Code: 30 + 40 %>'

代码表达式构建器的真正魅力在于,您可以在非数据绑定情况下像表达式一样使用数据绑定。您还可以创建其他执行其他功能的表达式生成器。

web.config:

<system.web>    
    <compilation debug="true">
        <expressionBuilders>
            <add expressionPrefix="Code" type="CodeExpressionBuilder" />

使这一切发生的CS类:

[ExpressionPrefix("Code")]
public class CodeExpressionBuilder : ExpressionBuilder
{
    public override CodeExpression GetCodeExpression(
        BoundPropertyEntry entry,
        object parsedData,
        ExpressionBuilderContext context)
    {            
        return new CodeSnippetExpression(entry.Expression);
    }
} 

1
标题中的“和其他”是什么意思?
Khaled Musaied 09年

好吧,我想我从来没有去过别人。
andleer

2
+1,非常酷的功能...这实际上与WPF的标记扩展非常相似
Thomas Levesque

这和使用不一样<%= /*code*/ %>吗?
bevacqua 2011年

33

ASHX文件类型的用法:
如果只想输出一些基本的html或xml而无需通过页面事件处理程序,则可以以一种简单的方式实现HttpModule

将页面命名为SomeHandlerPage.ashx,然后将以下代码(仅一行)放入其中

<%@ webhandler language="C#" class="MyNamespace.MyHandler" %>

然后是代码文件

using System;
using System.IO;
using System.Web;

namespace MyNamespace
{
    public class MyHandler: IHttpHandler
    {
        public void ProcessRequest (HttpContext context)
        {   
            context.Response.ContentType = "text/xml";
            string myString = SomeLibrary.SomeClass.SomeMethod();
            context.Response.Write(myString);
        }

        public bool IsReusable
        {
            get { return true; }
        }
    }
}

5
值得注意的是,如果需要,应该添加IRequiresSessionState或IReadOnlySessionState,否则它将不存在。
Tracker1

3
还值得注意的是,您可以在web.config中指定处理程序的设置,因此您不需要放置物理的ashx文件。或者,您可以从全局asax开始在应用程序中以编程方式注册处理程序。
菲尔



26

我开发了一个asp.net应用程序,该应用程序由一家领先的安全公司进行了安全审核,并且我了解了这个简单的技巧,可以防止一个鲜为人知但重要的安全漏洞。

以下说明来自:http : //www.guidanceshare.com/wiki/ASP.NET_2.0_Security_Guidelines_-_Parameter_Manipulation#Consider_Using_Page.ViewStateUserKey_to_Counter_One-Click_Attacks

考虑使用Page.ViewStateUserKey来抵抗一键式攻击。如果您对调用方进行身份验证并使用ViewState,请在Page_Init事件处理程序中设置Page.ViewStateUserKey属性,以防止一键式攻击。

void Page_Init (object sender, EventArgs e) {
  ViewStateUserKey = Session.SessionID;
}

将属性设置为您知道每个用户唯一的值,例如会话ID,用户名或用户标识符。

当攻击者创建一个网页(.htm或.aspx),该网页包含一个名为__VIEWSTATE的隐藏表单域且已经填充ViewState数据时,就会发生一键式攻击。可以从攻击者先前创建的页面(例如包含100个项目的购物车页面)生成ViewState。攻击者诱使毫无戒心的用户浏览该页面,然后攻击者导致该页面被发送到ViewState有效的服务器。服务器无法知道ViewState源自攻击者。ViewState验证和HMAC无法抵抗这种攻击,因为ViewState有效并且页面是在用户的安全上下文下执行的。

通过设置ViewStateUserKey属性,当攻击者浏览到一个页面以创建ViewState时,该属性将初始化为他或她的名字。当合法用户将页面提交到服务器时,将使用攻击者的名称对其进行初始化。结果,ViewState HMAC检查失败,并生成异常。


2
还记得离开base.OnInit(e); 让Page_Init()函数完成其工作。
德鲁伊2009年

我认为,如果实际用户不接受cookie或sessionid超时,则此技巧可能会失败。
亚里士多德(Aristos)2010年

1
base.OnInit(e);如果您正在使用AutoEventWireup="true"该页面,则不需要。
亚当·诺夫辛格

1
德鲁伊:他没有重写OnInit(在这种情况下,base.OnInit(e)是必要的)。
crdx

仅在会话实际启动后才能将会话ID用于ViewStateUserKey。这也意味着会话过期后这些页面可能会超时。如果您担心这些问题,则可以考虑使用更耐用的产品,例如用户的IP地址。
RickNZ


20

包含在ASP.NET 3.5 SP1中:

  • customErrors现在支持值为“ ResponseRewrite”的“ redirectMode”属性。显示错误页面而不更改URL。
  • 现在,表单标签可以识别动作属性。非常适合在使用URL重写时

20

面板中的DefaultButton属性。

它为特定面板设置默认按钮。


1
注意,不适用于所有类型的按钮,例如LinkBut​​tons!
2011年


19

使用configSource拆分配置文件。

您可以使用web.config文件中的configSource属性将配置元素推送到其他.config文件,例如,而不是:

    <appSettings>
        <add key="webServiceURL" value="https://some/ws.url" />
        <!-- some more keys -->
    </appSettings>

...您可以将整个appSettings部分存储在另一个配置文件中。这是新的web.config

    <appSettings configSource="myAppSettings.config" />

myAppSettings.config文件中:

    <appSettings>        
        <add key="webServiceURL" value="https://some/ws.url" />
        <!-- some more keys -->
    </appSettings>

这对于将应用程序部署到客户并且不希望他们干扰web.config文件本身并且只希望他们能够仅更改一些设置的情况非常有用。

参考:http : //weblogs.asp.net/fmarguerie/archive/2007/04/26/using-configsource-to-split-configuration-files.aspx


1
这也适用于任何类型的.net项目,例如Desktop app。配置
Zoltan Veres 2010年



16

默认情况下,自定义控件的标记之间的任何内容都将添加为子控件。可以在AddParsedSubObject()重写中对其进行拦截以进行过滤或其他解析(例如,对LiteralControls中的文本内容进行解析):

    protected override void AddParsedSubObject(object obj)
     { var literal = obj as LiteralControl;
       if (literal != null) Controls.Add(parseControl(literal.Text));
       else base.AddParsedSubObject(obj);
     }

...

   <uc:MyControl runat='server'>
     ...this text is parsed as a LiteralControl...
  </uc:MyControl>

13

如果您让ASP.NET生成RSS源,则有时会在页面顶部加一行。这将无法使用常见的RSS验证器进行验证。您可以通过将page指令放在页面<@Page>底部来解决此问题。


7
使用.ASHX处理程序生成RSS提要更好吗?
Dan Diplo

我想这取决于项目的复杂性。并非每个人都有创建或编译处理程序的能力或技能。在页面中,asp.net对此非常有效
凯文·高夫

1
而且,您可以使用<asp:Repeater>之类的方法生成RSS项并执行其他技巧(例如使用LogInView删除某些项),这比从ASHX IMO中编写字符串要好得多
chakrit 2010年

LinqToXml + ASHX是必经之路!
卡洛斯·穆尼奥斯

这比RSS提要生成有用得多。IIRC,HTML5必须在顶部的第一行中具有<!doctype html>标记,才能正确验证。
罗伊·廷克

12

在ASP.NET v3.5添加路由之前,您只需在页面管道中编写HTTPModule并重写请求即可创建自己的友好URL(例如BeginRequest事件)。

类似http:// servername / page / Param1 / SomeParams1 / Param2 / SomeParams2之类的URL会映射到如下所示的另一页(通常使用正则表达式)。

HttpContext.RewritePath("PageHandler.aspx?Param1=SomeParms1&Param2=SomeParams2");

DotNetNuke有一个非常好的HttpModule,用于其友好的URL。对于无法部署.NET v3.5的计算机仍然有用。


这需要将所有IIS请求都映射到ASP.NET
John Sheehan

或者只是404错误处理程序。
FlySwat
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.