Características ocultas de ASP.NET
(30)
Esta pregunta existe porque tiene un significado histórico, pero no se considera una buena pregunta sobre temas para este sitio, así que no la use como evidencia de que puede hacer preguntas similares aquí.
Más información: https://stackoverflow.com/faq
Siempre hay características que serían útiles en escenarios marginales, pero por esa misma razón la mayoría de las personas no las conocen. Estoy pidiendo características que no suelen enseñarse en los libros de texto.
¿Cuáles son los que tú conoces?
Antes de que ASP.NET v3.5 agregase rutas, podría crear sus propias URL sencillas simplemente escribiendo un HTTPModule para volver a escribir la solicitud al principio de la canalización de la página (como el evento BeginRequest).
Urls como http://servername/page/Param1/SomeParams1/Param2/SomeParams2 se asignarán a otra página como la que se muestra a continuación (a menudo con expresiones regulares).
HttpContext.RewritePath("PageHandler.aspx?Param1=SomeParms1&Param2=SomeParams2");
DotNetNuke tiene un HttpModule realmente bueno que hace esto por sus URLs amigables. Sigue siendo útil para máquinas donde no se puede implementar .NET v3.5.
Aquí está el mejor. Agregue esto a su web.config para una compilación MUCHO más rápida. Esto es post 3.5SP1 a través de este QFE .
<compilation optimizeCompilations="true">
Resumen rápido: estamos introduciendo un nuevo conmutador optimeCompilations en ASP.NET que puede mejorar considerablemente la velocidad de compilación en algunos escenarios. Hay algunas capturas, así que sigue leyendo para más detalles. Este conmutador está actualmente disponible como QFE para 3.5SP1, y formará parte de VS 2010.
El sistema de compilación ASP.NET tiene un enfoque muy conservador que hace que borre cualquier trabajo anterior que haya realizado en cualquier momento en que se modifique un archivo de "nivel superior". Los archivos de "nivel superior" incluyen cualquier cosa en bin y App_Code, así como global.asax. Si bien esto funciona bien para aplicaciones pequeñas, se vuelve casi inutilizable para aplicaciones muy grandes. Por ejemplo, un cliente se encontraba en un caso en el que demoraba 10 minutos actualizar una página después de realizar cualquier cambio en el ensamblaje de un "contenedor".
Para aliviar el dolor, agregamos un modo de compilación ''optimizado'' que tiene un enfoque mucho menos conservador para la compilación.
Vía here :
Atributo MaintainScrollPositionOnPostback en la directiva Page. Se utiliza para mantener la posición de desplazamiento de la página aspx en las devoluciones de datos.
Compruebe si el cliente todavía está conectado, antes de iniciar una tarea de larga duración:
if (this.Response.IsClientConnected)
{
// long-running task
}
De forma predeterminada, cualquier contenido entre etiquetas para un control personalizado se agrega como un control secundario. Esto se puede interceptar en un reemplazo AddParsedSubObject () para el filtrado o análisis adicional (por ejemplo, del contenido de texto en 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>
Dos cosas se destacan en mi cabeza:
1) Puedes activar y desactivar Trace desde el código:
#ifdef DEBUG
if (Context.Request.QueryString["DoTrace"] == "true")
{
Trace.IsEnabled = true;
Trace.Write("Application:TraceStarted");
}
#endif
2) Puede crear varias páginas .aspx utilizando solo un archivo compartido de "código subyacente".
Construye un archivo .cs de clase:
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";
}
}
y luego puede tener cualquier número de páginas .aspx (después de eliminar .designer.cs y .cs code-behind que VS ha generado):
<%@ Page Language="C#" AutoEventWireup="true" Inherits="Namespace.Class1" %>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="tbLogin" runat="server"></asp: TextBox >
</div>
</form>
Puede tener controles en el ASPX que no aparecen en Class1, y viceversa, pero debe recordar revisar sus controles en busca de valores nulos.
Habilitar intellisense para MasterPages en las páginas de contenido
Estoy seguro de que este es un hack muy poco conocido
La mayoría de las veces, debe usar el método findcontrol y emitir los controles en la página maestra desde las páginas de contenido cuando desee usarlos, la directiva MasterType habilitará la inteligencia en Visual Studio una vez que lo haga.
solo agrega una directiva más a la página
<%@ MasterType VirtualPath="~/Masters/MyMainMasterPage.master" %>
Si no desea utilizar la ruta virtual y, en su lugar, utilice el nombre de clase
<%@ MasterType TypeName="MyMainMasterPage" %>
Obtenga el artículo completo here
HttpContext.IsCustomErrorEnabled es una característica genial. Lo he encontrado útil más de una vez. Aquí hay una breve publicación al respecto.
HttpContext.Items como una herramienta de caché de nivel de solicitud
Incluido en ASP.NET 3.5 SP1:
- customErrors ahora admite el atributo "redirectMode" con un valor de "ResponseRewrite". Muestra la página de error sin cambiar la URL.
- La etiqueta de formulario ahora reconoce el atributo de acción. Ideal para cuando estás usando reescritura de URL
Mientras realiza la prueba, puede recibir correos electrónicos enviados a una carpeta de su computadora en lugar de a un servidor SMTP. Pon esto en tu web.config:
<system.net>
<mailSettings>
<smtp deliveryMethod="SpecifiedPickupDirectory">
<specifiedPickupDirectory pickupDirectoryLocation="c:/Temp/" />
</smtp>
</mailSettings>
</system.net>
Modo de venta en el nivel machine.config:
<configuration>
<system.web>
<deployment retail="true"/>
</system.web>
</configuration>
Anula la configuración de web.config para aplicar la depuración a falso, activa los errores personalizados y desactiva el seguimiento. No se olvide más de cambiar los atributos antes de publicarlos, simplemente déjelos todos configurados para entornos de desarrollo o de prueba y actualice la configuración de producción minorista.
Propiedad DefaultButton en Paneles.
Establece el botón predeterminado para un panel en particular.
Puede usar los comentarios de ASP.NET dentro de una página .aspx para comentar partes completas de una página, incluidos los controles del servidor. Y los contenidos que se comentan nunca serán enviados al cliente.
<%--
<div>
<asp:Button runat="server" id="btnOne"/>
</div>
--%>
Puedes usar:
Request.Params[Control.UniqueId]
Para obtener el valor de un control ANTES se inicializa viewstate (Control.Text, etc., estará vacío en este punto).
Esto es útil para el código en Init.
ScottGu tiene un montón de trucos en http://weblogs.asp.net/scottgu/archive/2006/04/03/441787.aspx
Si coloca un archivo llamado app_offline.htm en la raíz de un directorio de aplicaciones web, ASP.NET 2.0+ cerrará la aplicación y detendrá el procesamiento normal de las nuevas solicitudes entrantes para esa aplicación, mostrando solo el contenido de app_offline.htm Archivo para todas las nuevas solicitudes .
Esta es la forma más rápida y fácil de mostrar su aviso de "Sitio no disponible temporalmente" mientras re-implementa (o retrocede) los cambios en un servidor de producción.
Además, como lo señala marxidad , asegúrese de tener al menos 512 bytes de contenido dentro del archivo para que IE6 lo represente correctamente.
Si tiene ASP.NET generando una fuente RSS, a veces colocará una línea adicional en la parte superior de la página. Esto no se validará con los validadores de RSS comunes. Puede <@Page>
colocando la directiva de página <@Page>
en la parte inferior de la página.
Trabajé en una aplicación asp.net que pasó por una auditoría de seguridad realizada por una empresa de seguridad líder y aprendí este truco fácil para evitar una vulnerabilidad de seguridad menos conocida pero importante.
La siguiente explicación es de: http://www.guidanceshare.com/wiki/ASP.NET_2.0_Security_Guidelines_-_Parameter_Manipulation#Consider_Using_Page.ViewStateUserKey_to_Counter_One-Click_Attacks
Considere el uso de Page.ViewStateUserKey para contrarrestar los ataques de un solo clic. Si autentica a las personas que llaman y usa ViewState, configure la propiedad Page.ViewStateUserKey en el controlador de eventos Page_Init para evitar ataques de un solo clic.
void Page_Init (object sender, EventArgs e) {
ViewStateUserKey = Session.SessionID;
}
Establezca la propiedad en un valor que sepa que es único para cada usuario, como un ID de sesión, un nombre de usuario o un identificador de usuario.
Un ataque con un solo clic ocurre cuando un atacante crea una página web (.htm o .aspx) que contiene un campo de formulario oculto llamado __VIEWSTATE que ya está lleno de datos de ViewState. El ViewState puede generarse a partir de una página que el atacante creó anteriormente, como una página de carrito de la compra con 100 artículos. El atacante atrae a un usuario desprevenido para que navegue hasta la página, y luego el atacante hace que la página se envíe al servidor donde es válido el ViewState. El servidor no tiene forma de saber que el ViewState se originó desde el atacante. La validación de ViewState y los HMAC no contrarrestan este ataque porque ViewState es válido y la página se ejecuta en el contexto de seguridad del usuario.
Al configurar la propiedad ViewStateUserKey, cuando el atacante navega a una página para crear el ViewState, la propiedad se inicializa con su nombre. Cuando el usuario legítimo envía la página al servidor, se inicializa con el nombre del atacante. Como resultado, la verificación HMAC de ViewState falla y se genera una excepción.
Una característica poco conocida y poco utilizada de ASP.NET es:
Rara vez se usa porque solo hay una situación específica en la que la necesitarías, pero cuando la necesitas, es muy útil.
Algunos artículos sobre esta característica poco conocida:
Mapeo de etiquetas en ASP.NET
Uso de la asignación de etiquetas en ASP.NET 2.0
y de ese último artículo:
La asignación de etiquetas le permite intercambiar controles compatibles en tiempo de compilación en cada página de su aplicación web. Un ejemplo útil es si tiene un control ASP.NET de valores, como DropDownList, y desea reemplazarlo con un control personalizado que se deriva de DropDownList. Este podría ser un control que se haya personalizado para proporcionar un almacenamiento en caché más optimizado de los datos de búsqueda. En lugar de editar cada formulario web y reemplazar las DropDownLists integradas con su versión personalizada, puede hacer que ASP.NET lo haga por usted modificando web.config:
<pages>
<tagMapping>
<clear />
<add tagType="System.Web.UI.WebControls.DropDownList"
mappedTagType="SmartDropDown"/>
</tagMapping>
</pages>
Uso del tipo de archivo ASHX:
Si solo desea generar algunos html o xml básicos sin pasar por los manejadores de eventos de la página, puede implementar HttpModule de una manera sencilla
Nombre la página como SomeHandlerPage.ashx y simplemente coloque el siguiente código (solo una línea)
<%@ webhandler language="C#" class="MyNamespace.MyHandler" %>
Luego el archivo de código
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; }
}
}
}
HttpModules . La arquitectura es una locura elegante. Tal vez no sea una característica oculta, pero no menos cool.
HttpContext.Current.IsDebuggingEnabled
Esto es genial para determinar qué secuencias de comandos se emitirán (versiones mínimas o completas) o cualquier otra cosa que desee en dev, pero no en vivo.
Configuración de las propiedades de control del servidor en función del navegador de destino y more .
<asp:Label runat="server" ID="labelText" ie:Text="This is IE text" mozilla:Text="This is Firefox text" Text="This is general text" />
Esa me tomó por sorpresa.
El generador de expresiones de código
Marcado de la muestra:
Text = ''<%$ Code: GetText() %>''
Text = ''<%$ Code: MyStaticClass.MyStaticProperty %>''
Text = ''<%$ Code: DateTime.Now.ToShortDateString() %>''
MaxLenth = ''<%$ Code: 30 + 40 %>''
La verdadera belleza del generador de expresiones de código es que puede usar el enlace de datos como expresiones en situaciones sin enlace de datos. También puede crear otros Expression Builders que realizan otras funciones.
web.config:
<system.web>
<compilation debug="true">
<expressionBuilders>
<add expressionPrefix="Code" type="CodeExpressionBuilder" />
La clase cs que hace que todo suceda:
[ExpressionPrefix("Code")]
public class CodeExpressionBuilder : ExpressionBuilder
{
public override CodeExpression GetCodeExpression(
BoundPropertyEntry entry,
object parsedData,
ExpressionBuilderContext context)
{
return new CodeSnippetExpression(entry.Expression);
}
}
Usando configSource para dividir archivos de configuración.
Puede usar el atributo configSource en un archivo web.config para enviar elementos de configuración a otros archivos .config, por ejemplo, en lugar de:
<appSettings>
<add key="webServiceURL" value="https://some/ws.url" />
<!-- some more keys -->
</appSettings>
... puede tener la sección completa de ajustes de aplicaciones almacenada en otro archivo de configuración. Aquí está el nuevo web.config
:
<appSettings configSource="myAppSettings.config" />
El archivo myAppSettings.config
:
<appSettings>
<add key="webServiceURL" value="https://some/ws.url" />
<!-- some more keys -->
</appSettings>
Esto es muy útil para los escenarios en los que implementa una aplicación para un cliente y no quiere que interfieran con el archivo web.config en sí, sino que solo quieran cambiar algunas configuraciones.
WebMethods.
Puede utilizar devoluciones de llamada de ASP.NET AJAX a métodos web colocados en páginas ASPX. Puede decorar un método estático con los atributos [WebMethod ()] y [ScriptMethod ()]. Por ejemplo:
[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();
}
Ahora, en tu página ASPX puedes hacer esto:
<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>
Y llame al método del lado del servidor a través de JavaScript usando:
<script type="text/javascript">
function GetFruit(l)
{
PageMethods.GetFruitBeginingWith(l, OnGetFruitComplete);
}
function OnGetFruitComplete(result)
{
alert("You got fruit: " + result);
}
</script>
throw new HttpException(404, "Article not found");
Esto será capturado por ASP.NET que devolverá la página customErrors. Aprendí sobre esto en una reciente publicación de .NET Tip of the Day
HttpContext.Current siempre le dará acceso a la Solicitud / Respuesta / etc del contexto actual, incluso cuando no tenga acceso a las propiedades de la página (por ejemplo, de una clase de ayudante con acoplamiento flexible).
Puede continuar ejecutando el código en la misma página después de redirigir al usuario a otro llamando a Response.Redirect ( url , false )
No necesita archivos .ASPX si lo único que desea es una página compilada (o cualquier IHttpHandler ). Simplemente configure la ruta y los métodos HTTP para que apunten a la clase en el elemento
<httpHandlers>
en el archivo web.config.Un objeto Page se puede recuperar de un archivo .ASPX mediante programación llamando a PageParser.GetCompiledPageInstance (virtualPath, aspxFileName, Context)