Exploring the depths and potentials of ASP.NET RSS 2.0 or Subscribe to .BenRush by Email
 Monday, May 08, 2006

Up until now I've blogged about peripheral topics, the bits surrounding the actual functional core of the Atlas framework. All-in-all, a lot of technology comes into play from the clientside to the serverside to make the end-effect seemless for both the end-user and the developer. At the end of the day, however, the basic concept is still that of the partial postback - which posts back to the server without causing an interrupt to the client experience. The "core" behind this whole concept centers around what is communicated with on the server; for browsers are capable of partial postbacks out of the box, but we - as developers - are tasked with building an infrastructure on the server to be communicated with by the client. It might be confusing to use the word "endpoint" as it's something that is a buzzword for WCF too, but it's a good word and useful for our purposes too; so I'll go as far as to say there are four endpoints available for communication on a Atlas-ified server:

  1. Inline [WebMethod]s within an .ASPX page,
  2. Authentication/authorization and personalization services,
  3. Webservice (.asmx) files located within the web application,
  4. Webservices of any type located beyond the current web application.

Atlas supports the web client communicating with any of these endpoints using its services. In a previous blogpost I discussed how the technology supports calling [WebMethod]-decorated functions written inline with .aspx files, but I have mostly focused on the clientside when it comes to communicating with webservices and the authentication/authorization infrastructure available. To a degree I discussed how the authentication/authorization/personalization services are structured too - but, for the sake of completion, I'll briefly discuss each and then go a bit further into how the webservices are included into the whole communication network.

Okay... so we have a client, and on that client there exists script that is based on, probably, the Atlas client framework making requests back to our server (though this isn't necessary). If the client is talking to a webmethod hosted on an .aspx page, it includes special variables in its form post to hint to the server-side framework that it must intercept the rendering phase of the .aspx page and, instead, formulate a call to the proper [WebMethod]-decorated function and have its output serialized back to the client. This, effectively, short-circuits the normal rendering phase of the page itself and provides the client with the bits it expects for its RPC-style call to our [WebMethod].

The other option is that the client needs to gather information regarding the authentication/authorization of the user, or the user's personalized bits. In this case, the client calls to the server with a specially formulated query-string that is comprised of the fully-qualifed name of the type that will support the call, including any variables in the form-post. The server-side framework intercepts this and processes it accordingly.

However, I see that most developers will simply create a new .asmx file and have their client call it, or instead, have their client call a ready-made webservice located outside of their project space (even on another server) in the case of mashups, et al. That's the case with endpoints 3 & 4 above. What's interesting is that I have completely left this discussion out until now. Honestly? I did this I was circling the core, so to speak, and trying to understand the client space first.

Infrastructurally, if you were Microsoft, it would make sense to try your darndest to maintain a consistency in the server-side code when dealing with these four options to prevent as much code-copy as possible. Technically, each one of these endpoints can be represented by a full-fledged .Net framework type: Inline webmethods exist within a compiled .ASPX page, authentication/authorization and profile services exist as types within Microsoft.Web.Atlas, and the webservices can have proxies generated for them (by wsdl.exe) that can be seen as strongly-typed representations for consumption by .Net. As a result, you would want to try trapping the incoming request, turn it into something that looks and feels like a casual .Net method call by generating your parameter stack and, then, executing the method (whether it be a proxy method or not). Have a gander at a few entries in a standard web.config file for a Atlas application:

.....
        <buildProviders>
            <add extension=".asbx" type="Microsoft.Web.Services.BridgeBuildProvider" />
        </buildProviders>
.....
        <httpHandlers>
            <remove verb="*" path="*.asmx"/>
            <add verb="*" path="*.asmx" type="Microsoft.Web.Services.ScriptHandlerFactory" validate="false"/>
            <add verb="*" path="*.asbx" type="Microsoft.Web.Services.ScriptHandlerFactory" validate="false"/>
        </httpHandlers>

        <httpModules>
            <add name="ScriptModule" type="Microsoft.Web.Services.ScriptModule"/>
            <add name="BridgeModule" type="Microsoft.Web.Services.BridgeModule"/>
        </httpModules>
.....

The <add name="ScriptModule" type="Microsoft.Web.Services.ScriptModule"/> entry actualizes inline [WebMethod] calls by punching in our own .Render implementation. We know this, but what of the rest? First, take note of the ScriptHandlerFactory type used as the handler factory for .asmx and .asbx file requests. A client will call a .asmx file if it wants to call a web service method, and a client will call a .asbx file if it wants to call a webservice method located on another web application (this is called bridging). Browsers are very careful not to do cross-site communication with script for security reasons - and so if the client wants to get a resource using script on another site, it must have the server do the call for it; so the server, then, acts like a "bridge" or middle-man. You call methods in a .asbx file if you want to call a bridged web service method. We have explained away the basics of how endpoints 1, 3, & 4 work. 2 - or the profile/authentication/authorization services are done through .asmx calls too - so, technically this is also handled by the ScriptHandlerFactory. So, to recap thus far:

  1. Inline [WebMethod]s within an .ASPX page - supported by Microsoft.Web.Services.ScriptModule
  2. Authentication/authorization and personalization services - supported by Microsoft.Web.Services.ScriptHandlerFactory
  3. Webservice (.asmx) files located within the web application - supported by Microsoft.Web.Services.ScriptHandlerFactory 
  4. Webservices of any type located beyond the current web application - supported by Microsoft.Web.Services.ScriptHandlerFactory.

The type, Microsoft.Web.Services.ScriptHandlerFactory does a lot of work, then. How does it differentiate the different requests, and what does it do internally? Again, I crack open Lutz Roeder's .Net Reflector and looked inside Microsoft.Web.Atlas (which houses all of the code for Atlas - and I mean all). After bouncing around for a while, I discovered that the calls are all REST-based, and that there exists an internal RestHandler which inherits IHttpHandler and is used for all these requests (calls are routed to it by the ScriptHandlerFactory). Within it's ProcessRequest method (called by the framework to process the request), there exists a fairly daunting looking hunk of code - only a few lines of code, however, are noteworthy:

IDictionary<string, object> dictionary1 = this.GetRawParams(context);
object obj1 = Activator.CreateInstance(this._webServiceMethodData.Owner.Type);
DataService service1 = obj1 as DataService;
if (service1 != null)
{
   service1.IsCalledRemotely = true;
}
object obj2 = this._webServiceMethodData.CallMethodFromRawParams(obj1, dictionary1);

Take note of the line containing Activator.CreateInstance(). This tells us that we're basically talking to a real data type (as I hinted at earlier). The result of this call (obj2) is worked on a bit by some plumbing code and returned to the client - but this is the bulk of the code. So, the question still exists, then: how are steps 2, 3 & 4 being dehydrated to basic .Net types that can be instantiated? The secret lies within the method .CreateHandler() of the type RestHandler:

internal static IHttpHandler CreateHandler(HttpContext context)
{
   WebServiceData data1 = WebServiceData.GetWebServiceData(context.Request.Path);
   string text1 = context.Request.QueryString["mn"];
   return RestHandler.CreateHandler(data1, text1);
}

This method creates a RestHandler to handle the incoming request, but also makes a weird call to WebServiceData.GetWebServiceData() passing to it the request path (the virtual path) to the resource (note, also, that it strips out the "mn" or method-name parameter from the querystring and passes it on). We can assume that it is the WebServiceData type that wraps each of the three "method" types that we can automate since, as you can see above, _webServiceMethodData is used above to call our method. GetWebServiceData is an overloaded method, and the call eventually winds its way down to another rather large function that, pretty much, holds the key to everything:

internal static WebServiceData GetWebServiceData(string virtualPath, bool failIfNoData)
{
    virtualPath = VirtualPathUtility.ToAbsolute(virtualPath);
    Type type1 = WebServiceData._mappings[virtualPath] as Type;
    bool flag1 = false;
    if (type1 == null)
    {
        flag1 = HostingEnvironment.VirtualPathProvider.FileExists(virtualPath);
        if (flag1)
        {
            type1 = BuildManager.GetCompiledType(virtualPath);
        }
    }
    if ((type1 == null) && !flag1)
    {
        string text1 = null;
        int num1 = virtualPath.IndexOf("ScriptServices/");
        if (num1 != -1)
        {
            num1 += "ScriptServices/".Length;
            text1 = virtualPath.Substring(num1, (virtualPath.Length - num1) - 5);
            text1 = text1.Replace('/', '.');
            type1 = typeof(WebServiceData).Assembly.GetType(text1, false, true);
            if (type1 == null)
            {
                type1 = BuildManager.GetType(text1, false, true);
            }
        }
        else
        {
            try
            {
                text1 = Path.GetFileNameWithoutExtension(virtualPath);
                text1 = WebServiceData.DecryptString(text1);
                type1 = Type.GetType(text1);
            }
            catch
            {
            }
            if (type1 != null)
            {
                WebServiceData._mappings[virtualPath] = type1;
                WebServiceData._typeVirtualPath[type1] = virtualPath;
            }
        }
    }
    if (type1 != null)
    {
        return WebServiceData.GetWebServiceData(type1);
    }
    if (failIfNoData)
    {
        throw new InvalidOperationException();
    }
    return null;
}

Phew. Are you ready for the dive? I'm going to try reducing the workload for you so you can kind of reap the benefit of the time I took to crack it. First, notice that the beginning block of code basically looks to see if the file exists on disk (given its virtual path), and if so, then it returns back a compiled data type for this file. This solves the situation where the requested resource is a .asmx file, as we request that the runtime compile the .asmx file (and its associated code files) and return us a full-fledged .Net data type. The check in the code for the "ScriptServices/" string is what identifies the request as a personalization or authentication/authorization request. The end-result is the grepping of the data type from the current assembly for the proper type to return. Note that the type (type1) is given to another overloaded form of GetWebServiceData() - going further we see that this type is wrapped by the WebServiceData type, and this is how it is linked.

...now, after we have the wrapped type (from the code above), the RestHandler.CreateHandler() method in the second code-snippet above iterates over all types that are given the [WebMethod] attribute and builds a familiar array of methods we see being used in the first snippet of code: _webServiceMethodData. So, voila - we are then calling fully-qualified data types from beginning to end.

But, we are missing one final bit. What about the external services? We saw that local web services can be referenced using their virtual path and compiled and instantiated and executed appropriately by the runtime. This is where the final entry in the web.config file comes into play: <add extension=".asbx" type="Microsoft.Web.Services.BridgeBuildProvider" />.

A build provider is a snap-in for the build-time environment of ASP.Net where a developer can generate code for their own file type and have said code included into the final assembly(ies) for the web application. See here for more information, but the basic idea is that when the web application is asked to compile, the runtime will encounter your custom file type and look to see if there is a build provider available for it. This is how Microsoft added supported for the mysterious .asbx file type. Microsoft.Web.Services.BridgeBuildProvider (if we inspect the code) has support for parsing the XML within these files and generating a valid data type that wraps proxy methods for the external web service and provides for the runtime environment all necessary strings to pull when calling the external service. If you look at the goliath piece of code above (the last one) and see that the final bit of control lands on a line of code calling Path.GetFileNameWithoutExtension and Type.GetType(), etc. The type generated by the build provider for the bridge service generates a data type of the same name as the .asbx file (so, foo.asbx will generate a type called foo); and this type is compiled into the app code for the web application. The result? Stripping the file name and doing a get type on the resultant name will locate the data type built by the bridge build provider and return it back to our pipeline we saw earlier.

So...the end result:

  1. Inline [WebMethod]s within an .ASPX page - supported by Microsoft.Web.Services.ScriptModule and implemented by injecting our own .Render method to call [WebMethod] in page class.
  2. Authentication/authorization and personalization services - supported by Microsoft.Web.Services.ScriptHandlerFactory and type wrapped by WebServiceData exists in Microsoft.Web.Atlas.
  3. Webservice (.asmx) files located within the web application - supported by Microsoft.Web.Services.ScriptHandlerFactory and type wrapped by WebServiceData exists on disk as .asmx file.
  4. Webservices of any type located beyond the current web application - supported by Microsoft.Web.Services.ScriptHandlerFactory and type wrapped by WebServiceData is built by the bridge build provider.

kick it on DotNetKicks.com
Monday, May 08, 2006 12:16:17 AM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
Computing
Tracked by:
http://freewebs.com/aspxfaq/01/index.aspx [Pingback]
http://freewebs.com/toltom/00/sitemap17.html [Pingback]
http://freewebs.com/toltom/01/www-match-com.html [Pingback]
http://freewebs.com/toltom/14/sitemap15.html [Pingback]
http://freewebs.com/toltom/10/wachovia-center.html [Pingback]
"http://kevruublog.tripod.com/152.html" (http://kevruublog.tripod.com/152.html) [Pingback]
"http://kevruublog.tripod.com/32.html" (http://kevruublog.tripod.com/32.html) [Pingback]
"http://eydlxz.org/sitemap16.html" (http://eydlxz.org/sitemap16.html) [Pingback]
"http://apz50e.org/christian-credit-counselors.html" (http://apz50e.org/christia... [Pingback]
"http://topslots.nl.eu.org/12/sitemap2.html" (http://topslots.nl.eu.org/12/sitem... [Pingback]
"http://freewebs.com/amexa/31/upholstered-headboards.html" (http://freewebs.com/... [Pingback]
"http://freewebs.com/amexa/16/investment-strategies.html" (http://freewebs.com/a... [Pingback]
"http://freewebs.com/amexa/36/fix-computer.html" (http://freewebs.com/amexa/36/f... [Pingback]
"http://pinofranc.homestead.com/00/silver-jewelry.html" (http://pinofranc.homest... [Pingback]
"http://pinofranc.homestead.com/03/fruit-gift-baskets.html" (http://pinofranc.ho... [Pingback]
"http://pinofranc.homestead.com/03/gatlinburg-hotels.html" (http://pinofranc.hom... [Pingback]
"http://mdq3k-xxx.com/wife-sharing.html" (http://mdq3k-xxx.com/wife-sharing.html... [Pingback]
"http://z0poi-www.com/big-cock-suck.html" (http://z0poi-www.com/big-cock-suck.ht... [Pingback]
"http://batkoonews.tripod.com/186.html" (http://batkoonews.tripod.com/186.html) [Pingback]
"http://pohteenews.tripod.com/121.html" (http://pohteenews.tripod.com/121.html) [Pingback]
"http://maoguunews.netfirms.com/154.html" (http://maoguunews.netfirms.com/154.ht... [Pingback]
"http://n2t1j-ooo.com/young-boys-in-speedos-cocks.html" (http://n2t1j-ooo.com/yo... [Pingback]
"http://lasduunews.angelfire.com/33.html" (http://lasduunews.angelfire.com/33.ht... [Pingback]
"http://ccc2k-hhh.com/sex-search.html" (http://ccc2k-hhh.com/sex-search.html) [Pingback]
"http://u7tgq-xxx.biz/miami-escorts-outcall.html" (http://u7tgq-xxx.biz/miami-es... [Pingback]
"http://x8jji-www.biz/mature-panty.html" (http://x8jji-www.biz/mature-panty.html... [Pingback]
"http://ovx5a-eee.com/massage-m4m-los-angeles-erotic.html" (http://ovx5a-eee.com... [Pingback]
"http://freewebs.com/gremi/09/offering-337185.html" (http://freewebs.com/gremi/0... [Pingback]
"http://freewebs.com/amexa/17/cheap-airfare-com.html" (http://freewebs.com/amexa... [Pingback]
"http://freewebs.com/tferma/07/chiropractic-marketing-strategies.html" (http://f... [Pingback]
"http://freewebs.com/amexa/09/american-express-card.html" (http://freewebs.com/a... [Pingback]
"http://freewebs.com/gremi/11/circles-kinetic-dub-audiofly--priscilla-423070.htm... [Pingback]
"http://p5roc-rrr.com/teen-in-panties.html" (http://p5roc-rrr.com/teen-in-pantie... [Pingback]
"http://unibetkom.5gbfree.com/00107-blog.html" (http://unibetkom.5gbfree.com/001... [Pingback]
"http://ramambo.nl.eu.org/07/blink-182.html" (http://ramambo.nl.eu.org/07/blink-... [Pingback]
"http://harum.nl.eu.org/reconnect-aol.html" (http://harum.nl.eu.org/reconnect-ao... [Pingback]
"http://ramambo.nl.eu.org/hanging-rock-state-park-nc.html" (http://ramambo.nl.eu... [Pingback]
"http://znuv1h8.biz/fashion-schools.html" (http://znuv1h8.biz/fashion-schools.ht... [Pingback]
"http://digukl1.biz/joy-of-sex.html" (http://digukl1.biz/joy-of-sex.html) [Pingback]
"http://fomotkom.nl.eu.org/www-md-lottery-com.html" (http://fomotkom.nl.eu.org/w... [Pingback]
"http://narovkom.nl.eu.org/asian-teen-pussy.html" (http://narovkom.nl.eu.org/asi... [Pingback]
"http://gero--kom.nl.eu.org/playboy-model-galleries.html" (http://gero--kom.nl.e... [Pingback]
"http://freewebs.com/gabeganews/66.html" (http://freewebs.com/gabeganews/66.html... [Pingback]
"http://plxguhg.biz/bigsoccer-com.html" (http://plxguhg.biz/bigsoccer-com.html) [Pingback]
"http://reto--blog.nl.eu.org/sex-blend.html" (http://reto--blog.nl.eu.org/sex-bl... [Pingback]
"http://uykrmbb.biz/10-inch-dick.html" (http://uykrmbb.biz/10-inch-dick.html) [Pingback]
"http://zbbhywa.biz/all-free-twink-galleries.html" (http://zbbhywa.biz/all-free-... [Pingback]
"http://nasferablog.netfirms.com/273.html" (http://nasferablog.netfirms.com/273.... [Pingback]
"http://cypvori.biz/new-era-com.html" (http://cypvori.biz/new-era-com.html) [Pingback]
"http://nasferablog.netfirms.com/109.html" (http://nasferablog.netfirms.com/109.... [Pingback]
"http://vot--kom.nl.eu.org/airline-ticket-prices.html" (http://vot--kom.nl.eu.or... [Pingback]
"http://pure--kom.nl.eu.org/cheating-wives-fucking.html" (http://pure--kom.nl.eu... [Pingback]
"http://feha--mene.nl.eu.org/kids-having-sex.html" (http://feha--mene.nl.eu.org/... [Pingback]
"http://jafert--niko.nl.eu.org/ruvirgins.html" (http://jafert--niko.nl.eu.org/ru... [Pingback]
"http://nasferablog.netfirms.com/380.html" (http://nasferablog.netfirms.com/380.... [Pingback]
"http://zf1y1fs.biz/blluecross.html" (http://zf1y1fs.biz/blluecross.html) [Pingback]
"http://wwad6lf.biz/allegiantairlins.html" (http://wwad6lf.biz/allegiantairlins.... [Pingback]
"http://freewebs.com/fremapblog/sitemap4.html" (http://freewebs.com/fremapblog/s... [Pingback]
"http://freewebs.com/sruone/www-share-shutterfly-com.html" (http://freewebs.com/... [Pingback]
"http://freewebs.com/sruone/sitemap347.html" (http://freewebs.com/sruone/sitemap... [Pingback]
"http://galetgah.homestead.com/108.html" (http://galetgah.homestead.com/108.html... [Pingback]
"http://bmoesbi.info/guide-to-masterbation.html" (http://bmoesbi.info/guide-to-m... [Pingback]
"http://freewebs.com/vuter/00/tennis-court-dimensions.html" (http://freewebs.com... [Pingback]
"http://vuter.homestead.com/01/travel-quest.html" (http://vuter.homestead.com/01... [Pingback]
"http://euter.homestead.com/01/sitemap2.html" (http://euter.homestead.com/01/sit... [Pingback]
"http://duter.homestead.com/00/microsoft-words.html" (http://duter.homestead.com... [Pingback]
"http://freewebs.com/datingblogger/348.html" (http://freewebs.com/datingblogger/... [Pingback]
"http://freewebs.com/datingblogger/894.html" (http://freewebs.com/datingblogger/... [Pingback]
"http://fasxen.netfirms.com/7.html" (http://fasxen.netfirms.com/7.html) [Pingback]

Computers Blogs - Blog Top Sites

Archive
<January 2009>
SunMonTueWedThuFriSat
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567
Blogroll
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2009
Benjamin Rush
Sign In
Statistics
Total Posts: 444
This Year: 0
This Month: 0
This Week: 0
Comments: 128
Themes
Pick a theme:
All Content © 2009, Benjamin Rush
DasBlog theme 'Business' created by Christoph De Baene (delarou)