views:

181

answers:

4

I have a web service that is on an internal server. It can be called from any website on our network.

More and more developers are starting to use it. Current probably 20+ pages use this service, and the number is growing fast. I can see a year from now, someone asking what pages are using this service and what methods.

I would like to log the url of the pages that use my web service as the request come in. It would also be nice to know the method they are calling.I need to do something in such a way, that it does not affect the client web sites.My first thought was that I could write some code in the global.asax.

I have added some code to the Application_BeginRequest to log the request object details, but there does not appear to be anything about the requesting url.

What am I missing? Should I be looking at a different object?

Thanks.

A: 

Without implementing some sort of authentication, there isn't a guraenteeted way of knowing exactly who is calling your service - web metrics are the only way you can gauge what volume of traffic is hitting your service.

I'm sure you already know this but the whole point of a web service isn't to know or care who is calling it.

Chuck Conway
what if you're charging for your service? Wouldn't you want to know who's using it?
No Refunds No Returns
You'd have to use some sort of authentication. If you are requesting a user key because it's part of the business process (i.e. charging the user) then that's cool. But if you are requesting some sort of identity token because it's a limitation of the service architecture you've chosen then, from a purist sense, that's wrong.
Chuck Conway
+2  A: 

The only thing you can probably retrieve from the consumer is the IP address without changing your interface.

If you can change this you could do this e.g. by adding authentication and logging who is calling what, or by having some simple "token" principle.

However both methods require you to change the interface and therefore break backwards compatibility - which you should never do.

By always ensuring both back and forward compatibility you should not need to know exactly who is calling your service, but only that it is actually used.

veggerby
+2  A: 

Without disrupting existing users this is going to be difficult. The httpContect.Current.RequestUrl will just return the URL used to call your web service, not which web page called it.

The closest you can do without disrupting existing apps and forcing developers to change them is to grab the HttpContext.Current.Request.UserHostAddress, so you can at least get the IP of the machine calling your service.

Beyond this, what you might want to consider is adding a parameter to your functions for "CallingApp" and then log that in your code. That's pretty much what we did once re realized that we needed to know which apps are calling our service. We actually have an application monitoring service that uses a GUID for every new app we develop, and we pass that GUID to any web service. It[s extra work but to us it was critical because it allows us to know which apps will be affected when we need to perform updates or take the app server down for maintenance.

Edit - added

As a side note, at the point we realized we needed to track this, we had already been using web services for about a year. When faced with the same problem, we created a new set of web services, and included the extra field for the calling app in all of the new services, and then slowly went back and changed the older programs to point to the new services.

IN retrospect, we wish we had known we would need to do this up front because it created a lot of extra work. I'm guessing you'll be facing something similar if you really want to know exactly who is calling your services.

David Stratton
Wouldn't a header be better for tracking the usage? Adding a GUID for tracking purposes feels so dirty...
Chuck Conway
Actually, you can use whatever you want as long as it works for you. You can just have them send the URL to the calling page, or an application name, or any other method you want. We use the GUID because were already tracking our applications for error logging and other purposes, and already have GUID assigned to each app. Use what works best for you.
David Stratton
+1  A: 

@David Stratton

Thanks for your help. I think your suggestions were great. I accually did something very different, after your answer gave me some new ideas.

I should have mentioned that I was generating the web proxy that most of my users were using to make calls against my web service. My client in general do NOT use the proxy that Visual Studio creates.

Here is what did:

I generated my web proxy client again, and added calls to log the httpcontext of the client before every call. Because the proxy is running on the client, he had access to everything I needed. That allowed me to record everything about the client and the specific call they were making. I realize this would not work for most cases. But all of my clients are internal web sites.

It also had the advantage in that the clients did not have to modify their code at all. I just gave them all a new DLL. Problem solved. I get all the tracking data I want, and they did not have to modify their code.

I was stuck trying to solve the problem from the web service's point of view.

I realize that there is still a whole in this implementation, because someone does not have to use my client proxy to call my service. I guess I could force that at some point in the future. For now, they could let Visual Studio genereate a web proxy for my service. However, if they do that I guess I don't care. That is not the recommened way to call my service. I think the only one doing that is an ASP.NET 1.1 web site. When they upgrade, they will probably switch to my generated proxy.

Bobby Ortiz
Could you not use the IIS logs? They log the client IP, url requested.
MattC
Maybe. But I have way more control now.
Bobby Ortiz