I've a WCF web service method (over 3.5 NET Framework) which needs to be refactored to use optional input parameters. Mi investigation concluded optional parameteres as a concept is being introduced on 4.0 so I need to do some workaround to solve my issue. My code update looks like this:
partial class Class1: IService {
public int MethodName ( int param1, string param2 )
{
// code here
}
public int MethodName ( int param1)
{
// code here
string param2 = FillInInternally();
return this.MethodName(param1, param2);
}
I've also updated my operation contract:
[ServiceContract]
public interface IService
{
[OperationContract(Name = "Alias1")]
int MethoName(int param1, string param2);
[OperationContract(Name = "Alias2")]
int MethoName(int param1);
}
public partial class ServiceClient : ClientBase <IService>, IService
{
public int MethoName(int param1, string param2)
{
return Channel.MethodName(param1, param2);
}
public int MethoName(int param1)
{
return Channel.MethodName(param1);
}
}
Having that explained, I was able to get the Web Service correctly build. Besides oh that Integration Tests also ran perfectly. After that, I needed to install on the server and when trying to test the WSDL, I've faced an issu indicating an error on the svc file at column 1, row 1 ( please note I'm not including the exact error message because I rolled back the WS to the previous version to avoid prod issue during the weekend).
My question is: does somebody think I'm missing something from development? Or will I be able to get my WCF service method correctly overloaded when the "installation?" issues is solved?.
Any comments will be welcome.
Thanks,
.NET Framework 3.5
Visual Studio 2008 Standard Edition
C#
Are you manually constructing the ServiceClient class? I recommend you to use the svcutil.exe tool to generate the proxy and don't encourage yourself to do the modifications directly in the generated proxy code.
If you have generated the proxy through the tool or VS add service reference you should see the IService and the ServiceClient should look something like this,
[ServiceContract]
public interface IService
{
int Alias1(int param1, string param2);
int Alias2(int param1);
}
public partial class ServiceClient : ClientBase <IService>, IService
{
// other stuff
public int Alias1(int param1, string param2)
{
return base.Channel.Alias1(param1, param2);
}
public int Alias2(int param1)
{
return base.Channel.Alias2(param1);
}
}
Note that your client have the methods as Alias1 and Alias2 not MethodName. Please make sure yourself you have the right proxy to talk to service.
Related
I have a very strange and obscure issue with WCF services that I was hoping to get some insight on:
I am working a WCF service that we are building to replace one that we no longer have source code for. For some reason, in the new WCF service, everything is forced through a single paramater called "request". Using the WCF test client, this is what it looks like
On the "correct" service, this is what it looks like:
Is there any reason why this would be happening? I've defined all of the requests as follows:
[ServiceContract]
public interface IMyService
{
[OperationContract]
string SomeRequest();
}
Which seems correct, but there may be something I've overlooked that is causing this.
In your original WCF service, there is a request function parameter, and it has a definition similar to the following:
[ServiceContract]
public interface IMyService
{
[OperationContract]
Request SomeRequest(Request request);
}
[DataContract]
public class Request
{
string documentId;
[DataMember]
public string DocumentId
{
get { return documentId; }
set { documentId = value; }
}
}
In the new wcf service:
[ServiceContract]
public interface IMyService
{
[OperationContract]
string SomeRequest(string documentId);
}
So this is because the function parameters are different. Originally your parameter was class, but later changed to string, so the display in WCFTestClient is different.
In c# .Net Framework 4.5 (Visual Studio Ultimate 2012, Version 11.0.61219.00 Update 5), I'm trying to define a service variable at runtime for which webservice to use. Each webservice (there are many) are all defined the same except for the endpoint url but the credentials will not cross over to authenticate. The below condition is menial to simplify the issue at hand. The following code gives the error: Cannot implicitly convert type WebService2.Service to WebService1.Service.
What I've tried: calling functions to return the proper service but the parameters or assignment all require a specific type.
var service = new WebService1.Service();
service = new WebService2.Service();
I want to be able to use the variable service in the rest of the program without having to duplicate code everywhere for using the many web service references.
It seems like what you are looking to do, you would need a common interface between the two services so you could inject whichever service you wish to use.
public class WebService1 : IWebService {...service code}
public class WebService2 : IWebService{...service code}
public interface IWebService{...service methods you will be calling}
Then you could do the following.
IWebService service = new WebService1.Service();
service = new WebService2.Service();
Assuming that the different services share the same method names, you can create an interface that all of the services implement by using the interface
IMyService.cs
interface IMyService
{
void MyMethod(string filter);
}
MyWebServiceImplementation.cs
public class MyWebServiceImplementation : IMyService
{
public void MyMethod(string filter);
}
MySecondWebServiceImplementation.cs
public class MySecondWebServiceImplementation : IMyService
{
public void MyMethod(string filter);
}
MyImplemetationCode.cs
//Use different services from same variable
IMyService service = new MyWebServiceImplementation();
service.MyMethod("filter");
service = new MySecondWebServiceImplementation();
service.MyMethod("another filter");
I have several WCF services hosted in one console application. All of them are configured in code to use NetTcpBinding with binding.TransferMode = TransferMode.Streamed
Message contracts are used to define their operations (see code below for details)
RequestMsgContract1,
ResponseMsgContract1,
ResponseMsgContract2
For some mysterious reason I can not create a service reference for a service that uses
ResponseMsgContract1 and ResponceMsgContract2 message contracts simultaneously (see IMyService1 defenition below). The message I get is
The URI prefix is not recognized.
Metadata contains a reference that cannot be resolved: 'net.tcp://localhost:8890/MyService1/mex'.
Metadata contains a reference that cannot be resolved: 'net.tcp://localhost:8890/MyService1/mex'.
If the service is defined in the current solution, try building the solution and adding the service reference again.
Service references for two other services that use only RequestMsgContract1 and ResponseMsgContract2 (see IMyService2) or only RequestMsgContract1, ResponseMsgContract1 (see IMyService3) are created without any problems.
My question is What's wrong with my message contracts or where else should I look to find some clue?
I didn't paste my service configuration code here (as I said I do not use xml config file) because it works Ok for two of three services. I do not think the reason of error is there but you can find full code of service host console application here http://pastebin.com/1THhc9mU
// Can't create service reference for this service
[ServiceContract]
interface IMyService1
{
[OperationContract]
ResponseMsgContract1 Operation1(RequestMsgContract1 arguments);
[OperationContract]
ResponceMsgContract2 Operation2();
}
// No problems with service reference creation for this one
[ServiceContract]
interface IMyService2
{
[OperationContract]
ResponceMsgContract2 Operation1();
[OperationContract]
ResponceMsgContract2 Operation2(RequestMsgContract1 arguments);
}
// No problems with service reference creation for this one
[ServiceContract]
interface IMyService3
{
[OperationContract]
ResponseMsgContract1 Operation1();
[OperationContract]
ResponseMsgContract1 Operation2(RequestMsgContract1 arguments);
}
They use these three message contracts
[Serializable]
[MessageContract]
public class RequestMsgContract1
{
[MessageHeader(MustUnderstand = true)]
public Guid arg1;
}
[Serializable]
[MessageContract]
public class ResponseMsgContract1 : IDisposable
{
[MessageHeader(MustUnderstand = true)]
public long Length;
[MessageBodyMember(Order = 1)]
public System.IO.Stream stream;
public void Dispose()
{
if (stream != null)
{
stream.Close();
stream = null;
}
}
}
[Serializable]
[MessageContract]
public class ResponceMsgContract2 : IDisposable
{
[MessageHeader(MustUnderstand = true)]
public int Length { get; set; }
[MessageHeader(MustUnderstand = true)]
public string Str1 { get; set; }
[MessageBodyMember(Order = 1)]
public System.IO.Stream stream { get; set; }
public void Dispose()
{
if (stream != null)
{
stream.Close();
stream = null;
}
}
}
EDIT:
In case it is important to reproduce the problem here are my Visual Studio, .Net Framework and OS versions
Visual Studio 2012 (11.0.61030.00 Update 4)
.Net Framework Version 4.5.50709
Windows 8 Pro
I do not understand why the error I described in question happens but
no one has provided a proper answer yet so I'll tell about workarounds I came up with. Maybe it will help somebody.
I found two ways to make Visual Studio create Service References I need while preserving all the operations I want.
Error disappears if I rename ResponceMsgContract2.Length to
ResponceMsgContract2.Length2 so that ResponceMsgContract2 and
ResponseMsgContract1 do not have message headers with same name.
Why this helps is still a mystery to me. Maybe it's WCF bug.
Error disappears if I split IMyService1 to two interfaces:
[ServiceContract]
interface IMyService1_1
{
[OperationContract]
ResponseMsgContract1 Operation1(RequestMsgContract1 arguments);
}
[ServiceContract]
interface IMyService1_2
{
[OperationContract]
ResponceMsgContract2 Operation2();
}
Both variants are not good solutions and there may be situations when you can't apply any of them. But at least it's something.
recently have been successful getting my IIS hosted WCF service to work with basic authentication.
Since successfully implementing that. I have noticed that property values are not remembered.
Here is some code:
[ServiceContract]
public interface IEcho
{
string Message { [OperationContract]get; [OperationContract]set; }
[OperationContract]
string SendEcho();
}
public class EchoProxy : IEcho
{
public string Message { get; set; }
public string SendEcho()
{
return string.Concat("You said: ", Message);
}
}
public class EchoService : System.ServiceModel.ClientBase<IEcho>, IEcho
{
//-- ..... CONSTRUCTORS OMITTED ....
public string Message
{
get { return base.Channel.Message; }
set { base.Channel.Message = value; }
}
public string SendEcho()
{
return base.Channel.SendEcho();
}
}
Here is the console and the result:
EchoService client = new EchoService("SecureEndpoint");
client.ClientCredentials.UserName.UserName = "test";
client.ClientCredentials.UserName.Password = "P#ssword1";
client.Message = "Hello World";
Console.WriteLine(client.SendEcho());
Expected Result: You said: Hello World
Actual Result: You said:
I have Uploaded the sandbox project to my skydrive. I have included a SETUP.txt in the API project.
Click here to download.
How can I get properties to work?
thank you
I have never seen WCF contract used with a property to transfer data. i.e. the Message property. AFAIK its just not possible.
My recommendation would be to keep the concerns that are part of the contract separate, i.e. Operation and Data.
[ServiceContract]
public interface IEcho
{
[OperationContract]
string SendEcho(string Message);
}
Or
[ServiceContract]
public interface IEcho
{
[OperationContract]
string SendEcho(Message message);
}
[DataContract]
public class Message
{
[DataMember]
public string Message {get; set;}
}
At some later point you may wish to change the Message Object.
[DataContract]
public class MessageV2 : Message
{
[DataMember]
public DateTime Sent {get; set;}
}
While this changes the contract, changes like this can be backwardly compatible if managed carefully.
To understand what's happening, you need to know how the lifetime of the service object you're connecting to is configured. A good starting point is the MSDN article on Sessions, Instancing, and Concurrency.
For example, with InstanceContextMode.PerCall, a new service object will be created for each call, so no properties of the service object will be remembered between calls.
At the other end of the scale, InstanceContextMode.Single means a single instance handles all client requests for the lifetime of the application. In this case properties set by one client will be visible to all clients, not usually desirable.
In general, I would recommend using a stateless service object. But if you want a stateful service object (e.g. one with properties), you should use InstanceContextMode.PerSession, and (important) use a binding that supports sessions.
While I agree with #JTew that you shouldn't generally expose operations as properties, you will have the same problem if you try to use an object that stores state between calls in another way (such as a private field). I.e. the following would have exactly the same problem:
[ServiceContract]
public interface IEcho
{
[OperationContract]
void SetMessage(string message);
[OperationContract]
string GetMessage();
... etc ...
}
I've created the default WCF Service in VS2008. It's called "Service1"
public class Service1 : IService1
{
public string GetData( int value )
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract( CompositeType composite )
{
if ( composite.BoolValue )
{
composite.StringValue += "Suffix";
}
return composite;
}
}
It works fine, the interface is IService1:
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData( int value );
[OperationContract]
CompositeType GetDataUsingDataContract( CompositeType composite );
// TODO: Add your service operations here
}
This is all by default; Visual Studio 2008 created all this.
I then created a simple Winforms app to "test" this. I added the Service Reference to my the above mentioned service and it all works. I can instanciate and call myservice1.GetData(100); and I get the result.
But I was told that this service will have to be consumed by a Winforms .NET 2.0 app via Web Services, so I proceeded to add the reference to a new Winforms .NET 2.0 application created from scratch (only one winform called form1). This time, when adding the "web reference", it added the typical "localhost" one belonging to webservices; the wizard saw the WCF Service (running on background) and added it.
When I tried to consume this, I found out that the GetData(int) method, was now GetData(int, bool).
Here's the code
private void button1_Click( object sender, EventArgs e )
{
localhost.Service1 s1 = new WindowsFormsApplication2.localhost.Service1();
Console.WriteLine(s1.GetData(100, false));
}
Notice the false in the GetData call?
I don't know what that parameter is or where did that come from, it is called "bool valueSpecified".
Does anybody know where this is coming from? Anything else I should do to consume a WCF Service as a WebService from .NET 2.0? (winforms).
Well well… apparently here's the answer and possible solutions or workarounds.