Check this out: http://atlas.asp.net/docs/util/srcview.aspx?path=~/atlas/samples/services/WebMethodOnPage.src.
Note that, within the .aspx page source, there is a method written in C# decorated with the [WebMethod] attribute. What this means is that you have a standard .aspx page hosting a webmethod, which is typically exposed only on .asmx (webservice) files. What's going on here?
As it turns out, this is a new feature in Atlas and it utilizes an unsupported method exposed within the ASP.Net runtime: Control.SetRenderMethodDelegate. The documentation is fairly self-explanatory:
Assigns an event handler delegate to render the server control and its content into its parent control.
What this means is that you can inject your own handler function to render any control or page in the runtime, thereby circumventing its own rendering code: extremely powerful, albeit sort of a hack. Now, the way this works in the Altas framework is this:
private void Render(HtmlTextWriter output, Control container){ Page page1 = (Page) container; WebServiceData data1 = WebServiceData.GetWebServiceData(page1.AppRelativeVirtualPath); string text1 = page1.Request.Form["__serviceMethodName"]; WebServiceMethodData data2 = data1.GetMethodData(text1); string text2 = page1.Request.Form["__serviceMethodParams"]; try { IDictionary<string, object> dictionary1 = JavaScriptObjectDeserializer.DeserializeDictionary(text2); object obj1 = data2.CallMethodFromRawParams(page1, dictionary1); string text3 = JavaScriptObjectSerializer.Serialize(obj1, data2.Owner); output.Write(text3); } catch (Exception exception1) { HttpContext context1 = HttpContext.Current; context1.Response.StatusCode = 500; context1.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription(500); RestHandler.WriteExceptionJsonString(context1, output, exception1); }}
Look carefully at the implementation and see the method data2.CallMethodFromRawParams() and the output.Write(), which combine to push out to the response stream the serialized HTTP response from the webmethod. The rabbit hole goes deeper and deeper, but it really does us no good to go much further as we know how to look for methods based on their attributes and dynamically execute them from within the .Net runtime. The secret has been cracked, effectively, and we see how they're intercepting the normal request for an .aspx page and re-routing it to a new Render handler which calls the proper method in the page class.
It is the responsibility of the client framework, then, to include within the form post variables the ever-important __serviceMethodName variable. If you take a Fiddler trace of a request to the webmethod using one of the Microsoft samples, you can see it clearly in there:
POST /docs/atlas/samples/services/WebMethodOnPage.aspx HTTP/1.1Accept: */*Accept-Language: en-usReferer: http://atlas.asp.net/docs/atlas/samples/services/WebMethodOnPage.aspxContent-Type: application/x-www-form-urlencodedUA-CPU: x86Accept-Encoding: gzip, deflateUser-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)Host: atlas.asp.netContent-Length: 166Proxy-Connection: Keep-AlivePragma: no-cacheCookie: .....
__serviceMethodName=HelloWorld&__serviceMethodParams={"s":"asdfasdf"}&__VIEWSTATE=/wEPDwUKMjA4Mjk0NDk4M2Rk&nameTextBox=asdfasdf&__EVENTVALIDATION=/wEWAgLlssAyAouxhI4H
Remember Me
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.