views:

34

answers:

1

I have a common base class from which all my ASMX webservice classes will inherit. In the constructor, I want to do some common authentication checks; if they fail, I would like to halt processing right away (subclass's code would not get executed) and return a 401-status-code response to the caller.

However, the common ASPX-like ways of doing this don't seem to work:

  1. Context.Response.End(); always kicks back a ThreadAborted exception to the caller, within a 500-status-code response. Even if I explicitly set Context.Response.StatusCode = 401 before calling End(), it is ignored. The result is still a 500-response, and the message is always "thread-aborted-exception".
  2. MSDN suggests I use HttpContext.Current.ApplicationInstance.CompleteRequest() instead. However, this does not stop downstream processing: my subclass's functions are still executed as if the constructor had done nothing. (Kind of defeats the purpose of checking authorization in the constructor.)
  3. I can throw a new HttpException. This is a little better in that it does prevent downstream processing, and at least it gives me control over the exception Message returned to the caller. However, it isn't perfect in that the response is still always a 500.
  4. I can define a DoProcessing instance var, and set it to true/false within the constructor. Then have every single WebMethod in every single subclass wrap its functionality within an if (DoProcessing) block... but let's face it, that's hideous!

Is there a better / more thorough way to implement this sort of functionality, so it is common to all my ASMX classes?

edit: Accepting John's answer, as it is probably the best approach. However, due to client reluctance to adopt additional 3rd-party code, and some degree of FUD with AOP, we didn't take that approach. We ended up going with option #3 above, as it seemed to strike the best balance between speed-of-implementation and flexibility, and still fulfill the requirements.

A: 

The best way to do it would be to switch to WCF, which has explicit support for such a scenario.

If you must still use ASMX, then your best bet is to call the base class methods from each web method. You might want to use something like PostSharp to "magically" cause all of your web methods to call the base class method.

John Saunders
We decided against WCF for this system because it would be hosted on a different system, and thus all calls to it would be subject to XSS restrictions. JSONP works around that issue, but comes with its own set of limitations (GET-mode only, no cookie propagation from original asp.net server, etc.). WCF access needed to be secure, so we would've needed to work-around the JSONP-cookie limitation, then built a single-sign-on mechanism between the WCF service and the asp.net service. All of which isn't insurmountable, but ASMX seemed to be the more pragmatic approach.
mikemanne
@mike: what was the reason to host the WCF service on a different system? Why not just put it the exact same place you'd have put the ASMX service, and run it the exact same way?
John Saunders