I have a simple web application on Asp.net MVC. I created a WFC Service so I can get data to my Windows 8.1 app, but my new functions are not showing in my client side.
This My WFC code:
[DataContract]
public class Service1 : IService1
{
ApplicationDbContext _db=new ApplicationDbContext();
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public WtFImages.Models.Images GetDataL(int value)
{
var User = _db.Image.Local.FirstOrDefault(c => c.Id == value);
return User;
}
public List<WtFImages.Models.Images> GetDataAll(int value)
{
var GetAllPublic = _db.Image.Local.ToList();
return (GetAllPublic);
}
public IList<WtFImages.Models.Images> ZGetDataAll(int value)
{
var GetAllPublic = _db.Image.Local.ToList();
return (GetAllPublic);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
}
My client side only shows the default functions.
Iservice Code
namespace ImageFechingWfc
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
// TODO: Add your service operations here
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
}
Each method that you want to expose as service method, should exists in you IService1 interface and should be decorated with [OperationContract], then you should implement that method in service class.
Open IService1.cs and put signature of your methods is IService1 interface then decorate your new methods with [OperationContract], then put implementations in Service1 and rebuild the project, then add your service reference and use it.
Also You don't need that [DataContract] above your service implementation.
For example if you want to have an int Add(int x, int y) method in your service, put this in your IService1 interface:
[OperationContract]
int Add(int x, int y);
and then put this in your Service1 class:
public int Add(int x, int y)
{
return x+y;
}
To learn more about WCF services, you can read this Getting Started Tutorials
How to: Define a Windows Communication Foundation Service Contract
How to: Implement a Windows Communication Foundation Service Contract
How to: Host and Run a Basic Windows Communication Foundation Service
How to: Create a Windows Communication Foundation Client
How to: Configure a Basic Windows Communication Foundation Client
How to: Use a Windows Communication Foundation Client
First ensure that your methods are listed in wsdl or not ifnot then open the visual studio as administrator account and open from Visual C# Project File not Visual Studio Project User Options file (.user).
Related
Everyone! I have have custom WCF SOAP service (chatbot with getAnswer method that takes a string) and my client (website). My IService:
namespace WcfServiceLab1
{
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetChatbotAnswerUsingDataContract(string question);
}
}
Service.svc:
namespace WcfServiceLab1
{
public class Service1 : IService1
{
public string GetChatbotAnswerUsingDataContract(string question)
{
Chatbot chatbot = new Chatbot();
return chatbot.GetAnswer(question);
}
}
}
And my ChatbotController:
[HttpPost]
public ActionResult Create(string question)
{
try
{
ViewBag.ChatbotAnswer = obj.GetChatbotAnswerUsingDataContract(question.ToLower());
ViewBag.YourQuestion = question;
return View("Index");
}
catch
{
return View("Index");
}
}
It's works on localhost, but when I upload my WCF service on free hosting using FTP and try to add Service References Visual Studio didn't find my service. It's here: http://chatbotservice.esy.es/WcfServiceLab1/
How to "install" wcf service on the remote server? What should I do?
I have a Windows service that uses net.pipe as a WCF server and a Windows forms client to connect to it. There is a class called ConfigSettings that has values I want the client to query.
I want to have the client read the current values inside the serviceConfig instance that the service uses. Ultimately, I want the client to change values in it, but baby steps first.
The form can talk to the server via named pipes, but 'return serviceConfig is sending a new empty instance back to the client. I want the data that the service is actively using (that is, serviceConfig.Setting1 = x; serviceConfig.Setting2 = "foo"; )
The Windows service and WCF server code is (updated to working version):
using System.IO;
using System.ServiceModel;
using System.ServiceProcess;
namespace WindowsServiceTest
{
public partial class Service1 : ServiceBase
{
internal static ServiceHost myServiceHost = null;
//this is the master config that the service uses
public static ConfigSettings serviceConfig = new ConfigSettings();
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
if (myServiceHost != null)
{
myServiceHost.Close();
}
myServiceHost = new ServiceHost(typeof(WCFService1));
myServiceHost.Open();
//set active default settings
serviceConfig.Setting1 = 1;
serviceConfig.Setting2 = "initial.Setting2:" + serviceConfig.Setting1;
}
protected override void OnStop()
{
if (myServiceHost != null)
{
myServiceHost.Close();
myServiceHost = null;
}
}
}
public partial class WCFService1 : IService1
{
public ConfigSettings GetConfig()
{
return Service1.serviceConfig;
}
public void SetConfig(ConfigSettings sentConfig)
{
Service1.serviceConfig = sentConfig;
}
}
[ServiceContract]
public interface IService1
{
[OperationContract]
ConfigSettings GetConfig();
[OperationContract]
void SetConfig(ConfigSettings sentConfig);
}
public class ConfigSettings
{
public int Setting1 { get; set; }
public string Setting2 { get; set; }
public ConfigSettings() { }
}
}
The client retrieves the config like this (updated with some changes):
using System;
using System.ServiceProcess;
using System.Windows.Forms;
using WindowsServiceTest;
namespace WindowsServiceTestForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
ConfigSettings config = new ConfigSettings();
//GetConfig()
private void button1_Click(object sender, EventArgs e)
{
ServiceReference1.Service1Client myService = new ServiceReference1.Service1Client();
ServiceControllerPermission scp = new ServiceControllerPermission(ServiceControllerPermissionAccess.Control, Environment.MachineName, "Service1");//this will grant permission to access the Service
//get the current config and display
config = myService.GetConfig();
MessageBox.Show(config.Setting1 + "\r\n" + config.Setting2, "config");
myService.Close();
}
//SetConfig(ConfigSettings)
private void button2_Click(object sender, EventArgs e)
{ //make changes to values
config.Setting1 += 1;
config.Setting2 = "new.Setting2:" + config.Setting1;
ServiceReference1.Service1Client myService = new ServiceReference1.Service1Client();
ServiceControllerPermission scp = new ServiceControllerPermission(ServiceControllerPermissionAccess.Control, Environment.MachineName, "Service1");//this will grant permission to access the Service
//send the new config
myService.SetConfig(config);
myService.Close();
}
}
}
Update:
Maybe what I'm thinking needs to be done is overkill. It seems that I'm hitting a membrane between WCF and the Windows Service.
How would YOU approach this problem?
Windows Service that needs a Form for configuration.
When service starts, it loads a config.xml file from disk. (a serialized class)
When GUI starts, I want to:
retrieve its current configuration,
make some changes to it,
push it back to the service,
trigger service to re-read and react to the new configuration.
I was trying to avoid statically/writing the config file to disk and telling service to re-read it again. It "seemed" like WCF was the way to go.
Update 2
It seems that by just changing the master config in the service to static, the WCF service can access it directly. I could have sworn I did that originally before I posted, but I guess not.
I also separated the naming of Service1 to WCFService1 above, but it turns out that doesn't matter and works either way.
New complete code has been updated above.
You are getting confused between Windows Service and WCF Service - and have tried to have them both in the same class - while this is possible - it is probably easier to understand if you split them into two classes.
In your example the Windows Service starts, creates a new instance of itself as the WCF service then sets the config elements in the Windows Service instance, meaning the config is empty in the WCF Service instance.
try this instead
using System.ServiceModel;
using System.ServiceProcess;
namespace WindowsServiceTest
{
public partial class Service1 : ServiceBase
{
internal static ServiceHost myServiceHost = null;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
if (myServiceHost != null)
{
myServiceHost.Close();
}
myServiceHost = new ServiceHost(typeof(WCFService1 ));
myServiceHost.Open();
}
protected override void OnStop()
{
if (myServiceHost != null)
{
myServiceHost.Close();
myServiceHost = null;
}
}
}
public class WCFService1 : IService1
{
public WCFService1()
{
//change master settings from null
myConfig.Setting1 = "123";
myConfig.Setting2 = "456";
}
//this is the master config that the service uses
public ConfigSettings myConfig = new ConfigSettings();
public ConfigSettings GetConfig()
{
return myConfig;
}
}
[ServiceContract]
public interface IService1
{
[OperationContract]
ConfigSettings GetConfig();
}
public class ConfigSettings
{
public string Setting1 { get; set; }
public string Setting2 { get; set; }
public ConfigSettings()
{ }
}
}
There are a few ways of doing this (injecting dependencies in the service instance). I'll show two of them.
You have a special case here because the Windows Service is also your WCF service implementation. I think that soon enough you will want to separate them. So, my samples are based on a separate WCF service implementation.
The thing is that WCF has a concept of service instance mode. By default it is PerCall, meaning that a new Service1 instance is created to handle each request. This makes it a bit more difficult to inject something in these instances.
The simplest way is to set the instance mode to Single, meaning there will be only one Service1 instance handling all requests.
The second is easy to implement:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service1Implementation : IService1
{
private ConfigSettings _configSettings;
public Service1(ConfigSettings settings)
{
//now you have the settings in the service
_configSettings = setting;
}
...
}
//in the Windows Service
myServiceHost = new ServiceHost(typeof(Service1Implementation), new Service1Implementation(myConfig));
myServiceHost.Open();
The first solution involves you creating and specifying a service instance factory which the infrastructure will use later to create service instances per call.
The factory gives you the possibility to instantiate Service1 yourself and pass the config.
There is quite some code to be written for this, but I'll show the essential. For the complete solution, read this.
For you, it's easier to make the Windows Service just implement IInstanceProvider:
public class Service1 : ServiceBase, IInstanceProvider
{
private ConfigSettings _myConfig; //assign this member later on
...
//IInstanceProvider implementation
public object GetInstance(InstanceContext instanceContext, Message message)
{
//this is how you inject the config
return new Service1Implementation(_myConfig);
}
public object GetInstance(InstanceContext instanceContext)
{
return this.GetInstance(instanceContext, null);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
...
}
I will admit that it's been a while since I've touched WCF, but it looks to me like your ConfigSettings class is missing some attributes required to make it serializable via WCF.
using System.Runtime.Serialization;
[DataContract]
public class ConfigSettings
{
[DataMember]
public string Setting1 { get; set; }
[DataMember]
public string Setting2 { get; set; }
public ConfigSettings()
{ }
}
I don't believe having your Windows service operate as your WCF service, like other answers have suggested, is the problem. But I do agree that it's best to have them be separate classes.
I have a WCF service hosted on a console application the code is:
public interface ITestService
{
[OperationContract]
void SetField(string data);
[OperationContract]
string GetField();
}
public class TestService : ITestService
{
private string myData;
public string GetField()
{
retrun myData;
}
public void SetField(string data)
{
myData = data;
}
}
then I hosted it on a console application:
ServiceHost host = new ServiceHost(typeof(TestService));
host.Open();
Console.WriteLine("Test Service Host");
Console.WriteLine("Service Started!");
foreach (Uri address in host.BaseAddresses)
{
Console.WriteLine("Listening on " + address);
}
Console.WriteLine("Press any key to close the host...");
Console.ReadLine();
host.Close();
I started the console host then In an other console app I referenced the service and used it:
TestService client = new TestService();
client.SetField("test");
Console.WriteLine( client.GetField() );
this print nothing means the field is still null
What is wrong with this service?
What's wrong is that you're expecting that state will be persisted between calls - it is NOT. By default, WCF are absolutely stateless (and they should be! That's a good thing!)
If you need to persist information - store it into a persistent store (a.k.a a database).
Each WCF call will (by default) get a brand new, freshly created instance of TestService.
So your second call's instance knows nothing about the first instance (used by SetField) and therefore cannot return that value that you set in the first call.
Try this:
Use string as static.
public interface ITestService
{
[OperationContract]
void SetField(string data);
[OperationContract]
string GetField();
}
public class TestService : ITestService
{
private static string myData;
public string GetField()
{
retrun myData;
}
public void SetField(string data)
{
myData = data;
}
}
You should mark your service class with the attribute:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class TestService : ITestService
{
//...
}
This means that your service must have only one instance. And you must create the host like this:
var host = new ServiceHost(new TestService()); // or get a singleton..
host.Open();
Pay your attantion that you use an instance to create a service instead type. Then your code should work.
I have a Silverlight project that uses a WCF service that I created. My problem is that in my WCF service, I created a ServiceHost but VS2010 doesn't seem to recognize the instance of my object (underlines the svHost). Below is the code for my service.
using System;
using System.Collection.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Activation;
namespace userIO.Web
{
[ServiceContract]
public class CoordsService
{
[OperationContract]
public double xDir();
[OperationContract]
public double yDir();
[OperationContract]
public String keyPressed();
public class Coords : CoordsService
{
public double xDir { get; set; }
public double yDir { get; set; }
public String keyPressed { get; set; }
}
ServiceHost svHost = new ServiceHost(typeof(Coords), new Uri("http://localhost:8080"));
BasicHttpBinding binding = new BasicHttpBinding();
svHost.AddServiceEndpoint(typeof(CoordsService), binding, "");
svHost.Open();
}
}
Your ServiceContract should decorate an interface (a contract). The ServiceHost should host an instance of this interface and be outside the same service that it's hosting. At least I've only seen it done in this way.
The basic structure is:
[ServiceContract]
public interface IService
{
[OperationContract]
void DoSomething(Data data);
}
[DataContract]
public class Data
{
[DataMember]
int Num {get;set;}
}
public class Service : IService
{
public void DoSomething(Data data)
{ // do something }
}
// run in any other kind of app, console, win service, winform/wpf
static void Main()
{
ServiceHost svHost = new ServiceHost(typeof(Service), new Uri("http://localhost:8080"));
BasicHttpBinding binding = new BasicHttpBinding();
svHost.AddServiceEndpoint(binding, "");
svHost.Open();
}
An even easier solution to get your service up and running in VS2010 is to just create the service in a new WCF Service template. Take out their demo code, put in your own code for the servicecontract interface and the implementation service, then choose debug -> run and VS2010 will host the service for you without having to create an external app to run the service. Will also let you send data to the service to test out the code and the return values of your wcf functions in their simple winforms app.
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 ...
}