Ricordate come si chiamava ASP.NET prima della beta2 del framework 1.0?

Questo pezzetto di codice che si trova nella AppDomainFactory del Framework 2.0 (e 1.0) vi può aiutare:

if ((strUrlOfAppOrigin == null) || (strUrlOfAppOrigin.Length < 1))
{
    strUrlOfAppOrigin = "
http://localhost/ASP_Plus";
}

Ricordate ora?


Ieri sera, proseguendo nella mia operazione di speleologia informatica ho incontrato una cosa piuttosto strana che vi propongo: Stavo valutando la classe ISAPIRuntime, una delle classi che funge da interfaccia tra la parte unmanaged e quella managed della pipeline di ASP.NET. In realtà questa classe è il primissimo stadio della parte managed, e viene evocata per mezzo di COM Interop.

La classe ISAPIRuntime ha un metodo DoCGCollect() che suppongo venga chiamato dal runtime unmanaged per liberare le risorse. Qui ve lo propongo:

public void DoGCCollect()
{
      int num1;
      for (num1 = 10; (num1 > 0); num1 -= 1)
      {
            GC.Collect();
      }
}

In sostanza questo metodo non fa altro che chiamare la Collect() del Garbage Collector 10 volte... Inutile dire che sono molto perplesso; Uno si aspetterebbe di trovare raffinate tecniche di programmazione in condizioni così critiche.

Questo da l'impressione, piuttosto, di un ultimo tentativo di��"urlare forte" nella speranza che ci sia qualcuno in ascolto.

blog[at]boschin.it


La mia avventura nella pipeline continua.

E finalmente ho incontrato un'altra novità del framework. l'urlMapping.

L'urlMapping, è completamente assente dalla documentazione della beta ma nonostante questo sono riuscito a comprenderne il funzionamento con solamente un paio di tentativi andati a vuoto.

     enabled="true">
    

Questa sezione nel web.config fa in modo che se nella barra degli indirizzi del broswer digitiamo http://www.mysite.com/notexists.aspx in realtà mandiamo in esecuzione la pagina http://www.mysite.com/exists.aspx

Tutto molto semplice. Una cosa di questo tipo con il framework 1.1 comportava lo scrivere una bel po di codice per fare il path rewriting. Tipicamente un HttpModule. Ora nel framework viene aggiuunto un UrlMappingExecutionStep in testa a tutta la catena di eventi dell'applicazione:

...
list1 = new ArrayList();

if (flag1)
{
 list1.Add(new UrlMappingsExecutionStep(this));
}

this.CreateEventExecutionSteps(HttpApplication.EventBeginRequest, list1);
this.CreateEventExecutionSteps(HttpApplication.EventPreAuthenticateRequest, list1);
this.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest, list1);
...e così via...

Guardando il codice dello step di esecuzione del mapping si intuisce una cosa molto interessante; La querystring è parte costituente dell'url da mappare perciò è possibile usarla per redirigere il runtime su path diversi in caso di valori diversi; Vediamo il codice del metodo:

private void System.Web.HttpApplication.IExecutionStep.Execute()
{
   HttpContext context1 = this._application.Context;
   HttpRequest request1 = context1.Request;
   UrlMappingsConfig config1 = RuntimeConfig.GetConfig(context1).UrlMappings;

   if (config1 == null)
   {
   return;
   }
   string text1 = config1.UrlMappingsCollection[request1.RawUrl];

   if (text1 == null)
   {
      text1 = config1.UrlMappingsCollection[request1.Path];
   }
   if ((text1 != null) && (text1.Length > 0))
   {
      context1.RewritePath(text1, false);
   }
}

Rimarrà comunque la necessità di scrivere un HttpModule per esigenze un po' più raffinate.

blog[at]boschin.it


Scusate un attimo, fermi tutti... voglio sperare che io mi stia sbagliando, che abbia preso un abbaglio, che una svista non mi abbia fatto vedere la giusta strada...

Ma Visual Web Developer Express non compila le classi?

Lo so, dopo quasi un'intera giornata che lo uso avrei dovuto accorgermene, ma in realtà quest'oggi per testare il fw2.0 in velocità ho sempre scritto il codice direttamente nella pagina. Ora però, che sono arrivato al provare un HttpModule e quando mi sono trovato a scrivere il type nel web.config, mi sono reso conto che non sapevo cosa scrivere.

Un breve sguardo e...niente namespace, niente cartella bin, niente assembly!!!

Ma non si era detto che i prodotti express dovevano servire a chi desiderava imparare ad usare .NET?

Se questo è vero penso proprio che la prima lezione sia stata un fiasco.

Vi prego. Qualcuno mi smentisca.

blog[at]boschin.it


Guidato dall'insostituibile Reflector del buon Roeder, e grazie ad un po' di tempo disponibile, stamane ho deciso di "ficcare il naso" nella versione 2.0 della HttpPipeline di ASP.NET.

Come ovvio, di modifiche ce ne sono, ma vi anticipo una chicca che ho scoperto esaminando il meccanismo di accodamento delle richieste del runtime; Vediamo il seguente codice estratto dal reflector:

...
HttpRequestPriority priority1 = RequestQueue.GetRequestPriority(wr);

if ((priority1 != HttpRequestPriority.Critical) && (this._count >= this._queueLimit))
{
   HttpRuntime.RejectRequestNow(wr, false);
   return null;
}
this.QueueRequest(wr, flag1, (priority1 > HttpRequestPriority.Normal));
...

Siamo nella classe che governa l'accodamento delle richieste, e nella prima riga si legge la priorità della richiesta; Nel blocco "if", sostanzialmente si dice questo: se il limite di richieste accodabili è stato raggiunto e la priorità non è "critical" allora scarta la richiesta;

Questa di per se è già una novità, dato che nei framework precedenti una richiesta non godeva di una priorità. Il valore di HttpRequestPriority viene letto dal nodo system.web/httpRuntime del web.config. Se andate nella documentazione della beta1 e guardate tra gli attributi documentati vedrete che requestPriority semplicemente non esiste. Questo però sembra essere un errore della documentazione, perchè se invece leggete l'overview della classe HttpRuntimeSection (il wrapper dell'omonima sezione sezione del web.config) l'attributo esiste.

Non del tutto appagato della scoperta, ho deciso di spulciare il metodo QueueRequest, che tra i vari parametri accetta due boolean, "isLocal" e "isHighPri". Ecco il sorgente del metodo:

private void QueueRequest(HttpWorkerRequest wr, bool isLocal, bool isHighPri)
{
      RequestQueue queue1 = this;
      lock (queue1)
      {
            if (isLocal)
            {
                  this._localQueue.Enqueue(wr);
            }
            else if (isHighPri)
            {
                  this._highPriQueue.Enqueue(wr);
            }
            else
            {
                  this._externQueue.Enqueue(wr);
            }
            this._count += 1;
      }

      ...omissis...
}

Notate nulla di strano? Io credo di sì. La RequestQueue non è una, ma sono trè!

"Egli è uno e trino" potrei dire se fossi cattolico...

C'è una coda per le richieste locali, una per quelle esterne e una per quelle "critiche". Il fw considera locali le richieste provenienti da 127.0.0.1 (poteva essere diversamente) ed esterne tutte le altre.

La caratteristica delle richieste critiche è di essere accodate sempre (occhio, ho detto accodate, non eseguite), anche quando il limite massimo del workerprocess è stato raggiunto. Come si legge in un trafiletto della documentazione, questa caratteristica è stata aggiunta per poter avere delle pagine "ad accesso amministrativo" che consentano di effettuare manutenzioni anche in condizioni di altissimo carico del sistema. L'esatta dicitura è: "to change security properties on a portal site or to cancel long-running business-logic"

Un'ultima curiosità: Guardando nel metodo DequeueRequest() che ha l'incarico di estrarre una richiesta da una delle tre code, per mandarla in esecuzione la prima coda ed essere valutata è la local e non la critica come si sarebbe portati a pensare;

Morale? Se dovete fare una manutenzione su un server "sotto pressione" scendete nel datacenter e sedetevi davanti al server; Avrete molte più possibilità che questo vi ascolti... ;-)

Ok, passatemi la lanterna e fatemi largo; la buia tana del coniglio mi attende.

tags: - categories:

Al seguente link è possibile scaricare il setup e il sorgente di Paint.NET, un programma per l'editing di immagini scritto interamente in .NET; Ecco come descrivono il progetto gli autori:

"Paint.NET is a senior design project aided by a mentor at Microsoft.  It is a paint program designed entirely by students and written using Microsoft's .NET Framework.  The program makes it easier to create and edit photos. It maintains some of the best features of the original MS-Paint application and includes new, powerful tools. Such new tools include a history storage for undos and redos, and powerful multi-layering which is often seen only in high-quality, expensive photo-applications. This product was engineered with the latest in graphics and coding technology such as the new C# language from Microsoft, and the GDI+ graphics libraries. These programming frameworks allowed for the creation of a speedy, responsive application with an amazing array of graphic capabilities."

http://www.winisp.net/rbrewster/pdn.html


Sempre dal weblog di Sql Express ecco una tabella che riassume le differenze tra SQL Express e MSDE.

Particolare rilievo va secondo me alla dimensione massima del database supportata che sale da 2 a 4GB, alla mancanza del famigerato Workload governor che consentirà di superare il limite di 8 accessi concorrenti di MSDE e la presenza di un Sql Manager.

 

SQL Server Express 2005

MSDE 2000

DB Engine Features

·         Stored Procedures, Triggers, Views, & Cursors

·         Stored Procedures, Triggers, Views, & Cursors

Tools

·         SQL Express Manager

·         None

Database size

·         4 GB

·         2 GB

Programming

·         CLR + T-SQL

·         T-SQL

Workload support

·         1 CPU, 1 GB RAM

·         Workload Governor

Replication support

·         Transactional & Merge (Subscription only)

·         Full Merge only

Setup/Install

·         GUI, Command line, Silent

·         Command line, Silent

Application XCopy

·         Available

·         Not Available

DTS Runtime

·         Not Available

·         Available

XML Support

·         Native XML

·         Non-native support