Need help using a Service Reference in VS 2010 - wcf

This is my first time consuming a SOAP web service in ASP.Net and I am a little lost on how this works.
https://www.secureach.com/AchProcessorWebService/AchProcessorService.asmx
I created the Service Reference called AchProcessor in VS 2010 and now I have some Code hints in the VS editor. My first bit of code looks like this..
AchProcessor.WebServiceInfoRequest ws = new AchProcessor.WebServiceInfoRequest();
At this point I am kind of lost.. if I type ws. the only code hint I get is 'Body' with the exception of ToString, GetType etc...

Visual Studio would have generated the code using svcutil (or an app named along these lines) as you have seen, among such code is a proxy, or, a client, and this can be used as follows:
using (var client = new MyWebServiceClient())
{
var result = client.MyMethod();
}
So, in your case, MyWebServiceClient should be replaced with AchProcessorClient. As mentioned above by John Saunders, use the Object Browser to determine the definite name of the type if not so easily found as described here.
Although an appropriate binding for the service is most likely already in the configuration file, it is worth mentioning that you can actually specify the binding used in the constructor of the client, too.

Related

Add Service Reference "___ is already defined"a

I have a WCF web service that I am working on and I built it and was delighted to find that I could use complex types in it. I added some and then realized that they were still not useable as those types on the client end. This is an internal web service so these types are known on both sides. Anyway, that's not the problem, as I took the complex types out, but I think it may have left some residual issues.
When I then changed my additions to all be base types (string, date, int, etc) then added the web service to the client project, I got a "[enumtype] is already defined" error. It occurred in the reference.cs file so I opened it up. Sure enough there were duplicate enums. Plus there were a bunch of helper (serializing) functions. The duplicate enum was from code that had been in there before I picked this web service up to work on. It had not caused an issue previously.
I opened up the reference.cs for the previous (successful) service reference. It did not have the duplicates or functions and also I noticed a difference between the entries that were in there. The reference.cs that was failing to compile had this additional attribute in several places:
[System.ServiceModel.XmlSerializerFormatAttribute()]
I also see that my new failed code was using string[] and the old was using ArrayOfString. I did not intentionally change this, but must have somehow set something differently in the process.
Does anyone have a few clues?
Thanks!
Have you tried deleting the service reference from the project and re-adding it? You may have to manually remove some (or all) of the serviceModel contents too. If that is the only Service Reference then definitely remove the serviceModel element contents too.
Once its all gone, re-add the Service Reference. If you're still having problems then it may be that the service metadata is generating invalid WSDL causing the duplicate enums.
UPDATE: Just for verifying the WSDL is not valid, you could try creating the service proxy manually using the SvcUtil command line utility. It generates your proxy code like Visual Studio does and may give you more troubleshooting info.
After a lot of experimentation this is what I found out:
Our web service up to this point was using the Request / Response classes for input and output. There were required in 1.0, and were a carry over from that. I attempted to create a simple entry point that sent in a string and returned a string. This compiled ok, but:
Although you can use regular types for input and output, if you are using Request / Response types exchanges for other entry points, then you cannot.
Mixed method of request / response and regular types will compile, but it will not successfully import (at least into Visual Studio 2008). What ends up being created seems to be an attempt to create input and output classes for all of the functions to translate them to their complex types, along with the Request / Response types which creates duplicate entries and will not compile.
This then also means that you cannot send in a request object and return a string (which is how I found out that this was not allowed) – this generated an error in the unit test, which started me down this path.
So if you have a request / response web service, all functions must follow that protocol.

Capture global WCF ServiceHost request events

I'm using a really simple WCF project which is being hosted by a WPF application. It basically operates as a REST server for dishing up data on my PC. No IIS, and it runs as SingleInstance. I want to see what IP's are accessing MyService, and what WebMethod they're attempting to invoke.
Ok so I can have an event as part of my Service, declared in the service class itself. Here's some code that gets it going, it all works exactly as expected (no flames about m_ please ;)):
MyService ds = new MyService(); // It's not really called this :)
ds.Request += new EventHandler(ds_Request); // I want to avoid this
ds.SomePropertySetFromMyRehostingClient = "something"; // SingleInstance now required
m_Service = new ServiceHost(ds, new Uri(GetServerHostUri()));
m_Service.Description.Behaviors.Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single;
m_Service.BeginOpen(new TimeSpan(0, 0, 5), new AsyncCallback(EndStartService), null);
Then in each service method, I can raise this event so my app knows that someone has tried to use it. Brilliant, but let's face it, this is awful.
I have to write something along the lines of:
var who = OperationContext.Current.IncomingMessageProperties.Via;
var what = OperationContext.Current.IncomingMessageProperties["UriTemplateMatchResults"];
for each service call.
Is there a more generic catch-all-event that can detect a call to my service? There's probably one fired by one of the many Behaviour/ChannelDispatcher types which I admittedly don't fully understand.
Thanks for your help, Tom
Using IParameterInspector you can hook to any method calls and inspect the method and/or parameters.
There is no other way to get the extra information (IP address, etc) of the incoming message other than the one you have used. This is just a bad design by Microsoft IMHO (see my rant here).
You can find an example here.

I imported a WSDL, now what?

Web service newbie... Please bear with me.
I was given a WSDL file to import into my vb .NET project. I understand that this is a contract which is supposed to tell me how to use the related web service. That's where my problem comes in. I see all kinds of classes, properties, Interfaces, etc. in the imported service reference. Nothing telling me that "if you have X, Y, and Z as inputs call this function to return W".
At the risk of sounding too vague, what is it that I should be looking for that tells me how I should be using this? How do I know which functions to call and from what classes to call them from? Should I expect some documentation to be provided with the WSDL or is the WSDL supposed to be enough for me to look at it and say "ahh, that's how this is used!".
I've read through the various WSDL tutorials out on the web and they gave me a basic understanding (I think...?). I'm missing something somewhere though and I'm really sure where.
Thank you for any assistance.
The classes that have been generated are easy to use.
Basically you would have one client class, and in that class one method for each endpoint/operation declared in the WSDL.
In addition, there should be one class for each complex type defined in the XSD part (the operation input arg object and output result object).
You can then invoke your WS in a way similar to the following (simplified) example.
Try
Dim service As New MyServiceRef.MyServiceClient()
service.Open()
Dim output As MyServiceRef.myCallResponse
Dim args As New MyServiceRef.myCallRequest
args.arg1 = 1
args.arg2 = "A"
output = service.myCallRequest(args)
...
Catch ex As Exception
treat ( ex )
End Try
The WSDL will tell you or, perferably, a SOAP library how to communitcate with the SOAP server. A SOAP service can be an interface to get data for almost anything.
However, if the function names and parameters are not named well, it could be very vague what data you are to send to the SOAP service and what the response will be.
Most of the time, it should be documented. You should get those documents or learn what the service actually does from the service provider. The WSDL is not really meant to be for human consumption. Though, if you are writing your own XML, then yes, you'd need to pay attention to the WSDL. If a library is creating the XML for you, it usually works with the WSDL to find out how to structure the XML and read the response.
When you add reference of the web service, it creates a proxy for you to call the web methods on the server. Here is a simple tutorial for consuming web services in VB.NET

How should I handle differences with "Specified" fields in WCF services using VS 2010 vs VS 2008?

We're attempting to move to VS 2010 and we've noticed some odd behavior with our WCF services.
In VS 2008, when I add a given WCF service reference, for each object field that's not a reference type, the Object browser shows a fieldNameSpecified bool property. I realize that this exists so that there's a way to determine whether or not the value coming back from the service actually has a value, since DateTime, ints, etc can't be null.
When I try to add the same reference in VS 2010 (set to .Net 3.5), all of these fieldNameSpecified fields are missing. We have code that we wrote in VS 2008 that look at these fieldNameSpecified fields which causes our apps to be broken when attempting to use VS 2010 (because the proxies generated in VS 2010 don't have these fieldNameSpecified fields).
Is there a way to get VS 2010 to put these specified fields back in? Is there some other solution that won't require us to rewrite our code?
Also, what is the proper VS 2010 way of determining whether or not a value type field (int or DateTime) actually has valid data in it coming back from the service?
Any help GREATLY appreciated!
Clarification: The fieldNameSpecified fields are NOT part of the WSDL. VS 2008 apparently adds these into the proxy for you as a convenience...
I ran into an opposite situation recently. There wasn't any xxxspecified field before, but now they showed up. And we have only used VS2008. This acutally cause the value of the optional fields not being passed to the client application, since the xxxspecified fields are default to false.
If you look at both versions of the auto generated reference.cs file under your service reference, you should notice the difference. One uses DataContractSerializer, the other uses XMLSerializer.
When you add the service reference, if you use the URL for the service, e.g. http://localhost/MyService.svc, it would use DataContractSerializer. If you use the URL for the WSDL, e.g. http://localhost/MyService.svc?wsdl, it would use XMLSerializer.
You can use an attribute called EmitDefaultValue to resolve your problem as well. Follow these instructions:
http://bukovics.wordpress.com/2007/03/23/exposing-nullable-fields-to-net-11-web-service-clients/
This also explains why you get a fieldNameSpecified property. It's exactly what you need to fix your problem.
As I understand it, if the data contract requires the properties (for example, if you're using a [DataMember(IsRequired=true)] attribute), the "Specified" fields aren't auto-generated. Unfortunately, making the fields non-required would require a code change, but at least it wouldn't do so on the client.
An alternate way to allow callers to be able to not specify parameters (don't know if it's more VS 2010-ish than the "Specified" fields) is to use Nullable<> types.
I haven't tested it, but perhaps you could remove your Service References and instead put a pre-build step into your projects to run the old version of WSDL.exe to generate the proxies.

WCF ChannelFactory vs generating proxy

Just wondering under what circumstances would you prefer to generate a proxy from a WCF service when you can just invoke calls using the ChannelFactory?
This way you won't have to generate a proxy and worry about regenerating a proxy when the server is updated?
Thanks
There are 3 basic ways to create a WCF client:
Let Visual Studio generate your proxy. This auto generates code that connects to the service by reading the WSDL. If the service changes for any reason you have to regenerate it. The big advantage of this is that it is easy to set up - VS has a wizard and it's all automatic. The disadvantage is that you're relying on VS to do all the hard work for you, and so you lose control.
Use ChannelFactory with a known interface. This relies on you having local interfaces that describe the service (the service contract). The big advantage is that can manage change much more easily - you still have to recompile and fix changes, but now you're not regenerating code, you're referencing the new interfaces. Commonly this is used when you control both server and client as both can be much more easily mocked for unit testing. However the interfaces can be written for any service, even REST ones - take a look at this Twitter API.
Write your own proxy - this is fairly easy to do, especially for REST services, using the HttpClient or WebClient. This gives you the most fine grain control, but at the cost of lots of service API being in strings. For instance: var content = new HttpClient().Get("http://yoursite.com/resource/id").Content; - if the details of the API change you won't encounter an error until runtime.
Personally I've never liked option 1 - relying on the auto generated code is messy and loses too much control. Plus it often creates serialisation issues - I end up with two identical classes (one in the server code, one auto generated) which can be tided up but is a pain.
Option 2 should be perfect, but Channels are a little too limiting - for instance they completely lose the content of HTTP errors. That said having interfaces that describe the service is much easier to code with and maintain.
I use ChannelFactory along with MetadataResolver.Resolve method. Client configuration is a bother, so I get my ServiceEndpoint from the server.
When you use ChannelFactory(Of T), T is either the original contract that you can get from a reference in you project or a generated contract instance. In some projects, I generated the code from a Service Reference because I could not add a reference to the contract dll. You can even generate an asynch contract with the service reference and use that contract interface with ChannelFactory.
The main point of using ChannelFactory for me was to get rid of the WCF client config information. In the sample code below, you can see how to achieve a WCF client without config.
Dim fixedAddress = "net.tcp://server/service.svc/mex"
Dim availableBindings = MetadataResolver.Resolve(GetType(ContractAssembly.IContractName), New EndpointAddress(fixedAddress))
factoryService = New ChannelFactory(Of ContractAssembly.IContractName)(availableBindings(0))
accesService = factoryService.CreateChannel()
In my final project, the availableBindings are checked to use net.tcp or net.pipe if available. That way, I can use the best available binding for my needs. I only rely on the fact that a metadata endpoint exist on the server.
I hope this helps
BTW, this is done using .NET 3.5. However it does work also with 4.0.
Well in order to use ChannelFactory<T> you must be willing to share contract assemblies between the service and the client. If this is okay with you then ChannelFactory<T> can save you some time.
The proxy will build async functions for which is kind of nice.
My answer is a kind of summary of Keith's and Andrew Hare's answers.
If you do not control server, but have only WSDL/URL- generate proxy using Visual Studio or svcutil. (Note that Visual Studio sometimes failed, when svcutil works better).
When you control both server and client, share interfaces/contracts and call ChannelFactory
.
It's not just a matter of time saved. Using the WSDL generated proxy is dangerous because if you forget to update the service reference you can leave the solution in an inconsistent state. Everything compiles but the service contract is broken. I definetly suggest to use a ChannelFactory whenever possible, you make your life much easier.
A possible alternative could be to write a prebuild script that calls the SVCUtil utility to create the proxy everytime you build your project, but anyway ChannelFactory is much more neat and elegant.