I have built a WCF service using C# that is running on Windows server 2016.
I need to know when this WCF was called from the client, and who called it (for example the IP)
Is there a way to do this?
I have tried to check the event viewer, and the IIS, but did not get to know how.
Thanks,
You really should use some kind of logging framework ( Log4Net, NLog, MS enterprise library logger... ),
that will allow you to log into text file, email, event log or database, and you will then be able to first of all document any error/exception thrown from your code so that you can investigate and resolve bugs, plus you can then also include information / verbose level log entries to capture, as you say, caller IP and timestamp as well as calling parameters if you like and need to do so.
Logging every request best thing you can do. If you want to know how to get client ip in WCF, method below will work for you. Then you could log that ip, request time etc.
public string GetClientIp()
{
OperationContext operationContext = OperationContext.Current;
MessageProperties messageProps = operationContext.IncomingMessageProperties;
RemoteEndpointMessageProperty endpointProps = (RemoteEndpointMessageProperty)messageProps[RemoteEndpointMessageProperty.Name];
return endpointProps.Address;
}
you can try existing Log WCF Service Calls with Parameter information logging with system.diagnostics configuration
or create custom implementation for IOperationInvoker like here Log WCF Service Calls with Parameter information
Related
I have created a simple web service that receives data and saves it in a database. I need to create an application (or service) that will test the connection to this web service (from time to time, e.g. every 1 minute).
I need information like download, upload, ping and save them in the database. I tried NetworkInterface, but the web service is not an interface, so it cannot find it. I don't know how to test this connection and get information about it, so I need help.
Solution 1: fully custom
High level description:
Create a new endpoint , something like api/healthcheck
Either
a. do a mock action (save/delete false data
b. Maintain a table or any other persistence (even a singleton would do) with statistics from recent calls
Add them to a class response object and return it to the caller.
Solution 2: Use custom telemetry
High level description:
Pick a service like application insight: https://learn.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview
Configure the telemetry if the out of the box configuration isn't enough.
Use the rest api to get your information
I maintain an ASP.NET Web API project which supports a simple REST end point for clients to post XML data to our server. This site is setup to support BasicAuthentication and works very well. All of our security checks are done at the network firewall and on the machine itself using custom Windows User accounts. Recently, one of our clients requires that we support a SOAP end point to receive the XML data as well.
My thought was to simply add a new WebService (Blah.svc) with supporting interface having the required [ServiceContract] and [OperationContract] attributes to my interface. I had hoped that I could simply expose the URL to our client and it would "just work". I am able to hit the end point, but this service is not able to extract the user name.
Here is my sample code:
public string CreateWorkItem(string xml)
{
var userName = HttpContext.Current.User.Identity.Name;
if (string.IsNullOrEmpty(userName))
userName = "NO USER NAME";
var elem = XElement.Parse(xml);
return $"Hello [{userName}]! You sent [{elem.Value}].";
}
Here are my results:
I've scoured the web to try and find out how to get access to the BasicAuthentication details in a Soap message, but I'm not having any luck. All the examples that I'm finding require that I create a new WCF project and expose it with a lot of web.config settings, or the examples are ~5 years old using older techniques.
I'd like this service to simply publish with my WebAPI project using the Publish... option inside Visual Studio. Unfortunately, I've not found a common denominator to make it work. I'm sure I'm missing something, and I hope someone can help.
Any help would be greatly appreciated!
Check this link out: WCF Services and ASP.NET
In short you need to enable ASP.NET Compatibility in your WCF service.
However, you may want to look into using OperationContext.Current.ServiceSecurityContext.*
The fact that it is HttpContext.Current.User.Identity.Name is returning null means either:
User is null; or
User is Anonymous
I have a few ideas to help resolve the issue.
1. Your User.Name is actually null
You might want to debug by grabbing HttpContext.Current.User and see if it's correct.
2. Go direct: get the cookie via a parameter
Try and pass the HttpContext as a parameter so you can grab the cookie?
public string CreateWorkItem(HttpContext context, string xml)
{
var username = context.Current.User.Identity.Name;
...
}
3. Your configurations are not setup properly
The alternative is that maybe your web.config or Global.asax is not setup to properly.
I have written a WCF service with some regular functionality (add user, remove, search, update...). The implementation of this functionality is in entity framework (with sql DB).
Now I want to use it in the client side.
And I have some basic questions:
I have many calls to the WCF methods in the client side - should I try catch every time each call?
Every time I want to call a method, for example AddUser(User user), I need to make an instance of my service, like that:
WcfService client = new WcfService();
client.AddUser(user);
And in another place I write:
WcfService client = new WcfService(); //Again making a new instance...
client.UpdateUser(user);
Should I make one instance for all the application for my wcf service?
Or every time to make a new instance before I call to a method? (as in my example above).
Thanks very much !
In many cases, you want to reuse the same client proxy, as this connection method yields the best performance. Reusing the same proxy can be particularly beneficial if you use security features, which have a high initial security negotiation cost. Note: you surely need to check the state of the client proxy before using.
In the event that reusing the same client proxy is not an option, then consider using a ChannelFactory proxy that uses caching.
The following link provides a good explanation along with best practice recommendations:
http://blogs.msdn.com/b/wenlong/archive/2007/10/27/performance-improvement-of-wcf-client-proxy-creation-and-best-practices.aspx
(i)You can make an instance one time for a service, and use the same client whenever you need to make a method call. if you are aborting or closing the connection then you need to create each time.
(ii)It is better if you use try catch methods in each methods, so it will be easy to close the connection and identify the exceptions.
I have been searching the internet and have not been able to find a solution to my problem.
I want to be able to check the correctness and availability of a WCF service through a passed in endpoint. So the user inputs an endpoint (it changes a lot) and I want to be able to make sure it is valid by some form of ping or check.
I have been looking at MSDN but it does not seem to do what I am looking for.
You could set the OpenTimeout of your clients binding to a reasonable short time and call your clients Open() method.
If the service is not there/answering, you will get a System.ServiceModel.EndpointNotFoundException. Or your service could implement a "Ping()" method, that gives you a sensible result you can check, and call this "Ping()" without calling Open() first. So you can check availability and correctness with one call.
You could download excellent example from IDesign site (the writer of 'Programming WCF Services')
Here is the link: iDesign
Take a look on 'Ad-hoc Discovery' and 'Metadata Explorer'
I have a WSDL from which I generated the implementation of ClientBase namely MyService
function void updateData(Data data){
BasicHttpBinding binding = new BasicHttpBinding();
// see there is naked username and password.
EndpointAddress address = new EndpointAddress("http://qa.farwaha.com/eai_enu/start.swe?SWEExtSource=WebService&SWEExtCmd=Execute&UserName=john&Password=johspassword");
MyService service = new MyService(binding, address);
try{
service.update(data);
}finally{
service.close();
}
}
Unfortunately, to call this web service I have to pass User name and password as shown in the code. so, my question is around best practices.
Given that its a Winform Application.
How memory / CPU intensive is creating MyService object?
If you suggest cashing the service, it will hold on to the EndpointAddress; which intern has a string with Username and Password. Which is not a good idea .. any work arounds?
If I keep the code as such, service object will be garbage collected .. and there will be no trace of user name or password (as soon as GC runs)
This is a sample code, I have User Object which stores password in SecureString and every time I have to access the password; I get string from SecureString in an instance private method, use it quickly and let it be garbage collected. I believe if I use a method something like above, it will be safe OR safe enough rather than holding on to reference of Service, What do you suggest !!
To your specific questions:
In your client code, what you're constructing are instances of lightweight proxy classes that wrap the channel infrastructure that serialize messages to/from the service's endpoints. As such, these client proxy classes are cheap and fast to construct because they don't generally do a great deal until you actually send something to the service. One thing to watch out for is when you call services which employ a more complex security scheme - establishing connections to such services can be costly and so it's worth caching or re-using such connections if you can.
"Any workarounds"? Nope! Alas, the service you're consuming is poorly designed - not only do they require username and password to be supplied as part of the service method invocation, but they require that you pass them in the clear over HTTP. You might want to ask them to AT LEAST provide an SSL endpoint so that the username and password can be secured during transit. Better still, they could implement basic-auth to allow you to acquire an HTTP auth cookie that you can attach to subsequent calls against their services.
Yes, the GC will eventually clean-up your proxy instances. Better still, you could wrap your instances in using statements to invoke the Dispose pattern and clean-up deterministically. See my Magic8Ball WCF Service on Codeplex for examples.
Other observations:
Because your service requires your username and passoword, each time you call it, you need to pay some very careful thought to how you're going to obtain and store the username and password.
I would urge you to specify your binding information in the app.config rather than inline in your code. Again, see the Magic8Ball WCF Service: If you create bindings in code and the endpoint changes or if they open up a new endpoint, protocol, encoding and/or binding, you'll have to recompile and redist your entire app. If you specify your bindings in config, you might just be able to get away with shipping an updated app.config.
Hope this helps.